gpt4 book ai didi

java - 无法通过限定符注入(inject)

转载 作者:行者123 更新时间:2023-11-30 06:08:19 25 4
gpt4 key购买 nike

我有一个名为 Retry 的自定义注释,带有以下 Bean 后处理器:

@Component
public final class RetryBPP implements BeanPostProcessor {

private final Map<String, ClassDefinition> map = new HashMap<>(40);

@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
final Class<?> asClass = bean.getClass();
final Method[] methods = asClass.getMethods();
final List<Method> collect = Stream.of(methods)
.filter(method -> method.isAnnotationPresent(Retriable.class))
.collect(Collectors.toList());
if(!collect.isEmpty()){
this.map.put(beanName,new ClassDefinition(collect,asClass));
}
return bean;
}

@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
final ClassDefinition definition = this.map.get(beanName);
if(definition != null){
final Class beanClass = definition.baseCLass;
return Proxy.newProxyInstance(beanClass.getClassLoader(), beanClass.getInterfaces(), (proxy, method, args) -> {
if(definition.isMethodPresent(method)){
return this.retry(definition.originalMethod(method),bean,args);
} else{
return method.invoke(bean,args);
}
});
} else{
return bean;
}
}

private Object retry(final Method method,final Object originalBean,Object[] argc){
final Retriable retriable = method.getAnnotation(Retriable.class);
int attempts = retriable.attempts();
while(true){
try{
return method.invoke(originalBean,argc);
}catch (final Exception throwable){
if(this.support(retriable.exceptions(),throwable.getClass()) && attempts != 0){
attempts--;
log.warn("Error on method {} wait to repeat",method.getName());
this.sleep(retriable.delay(),retriable.timeUnit());
} else{
throw new RuntimeException(throwable);
}
}
}
}

@SneakyThrows(InterruptedException.class)
private void sleep(final long time, final TimeUnit timeUnit){
timeUnit.sleep(time);
}

private boolean support(final Class<? extends Exception>[] exceptions,Class<? extends Exception> exception){
boolean support = false;
for (Class _class : exceptions) {
if(_class.equals(exception)){
support = true;
break;
}
}
return support;
}

@AllArgsConstructor
private static final class ClassDefinition{
final List<Method> methods;
final Class baseCLass;

boolean isMethodPresent(final Method method){
return this.methods.stream()
.anyMatch(mthd->methodEquals(mthd,method));
}

Method originalMethod(final Method method){
return this.methods.stream()
.filter(mthd->methodEquals(mthd,method))
.findFirst().orElseThrow(NullPointerException::new);

}

}

}

界面:

public interface Inter {

String qqq(String url);

}

抽象类:

public abstract class Abs implements Inter {

@Override
@Retry
public String qqq(final String url) {
someLogic(url);
}

protected String someLogic(String str);

自定义限定符注释:

@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Target({ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.PARAMETER, ElementType.FIELD})
public @interface Qualif {

VV.v type();

}

和实现:

@Service
@Qualif(type = First)
@Slf4j
public final class Impl extends Abs {

@Override
protected String someLogic(String str){...}
}

当我像这样通过限定符 Autowiring 时:

@Autowired
@Qualif(type = First)
Inter inter;

Spring抛出异常没有找到依赖Inter的[com.devadmin.downloader.sites.VideoDownloader]类型的合格bean:,但是当我从abctract类中删除@Retry注释时,一切都很好。如何解决这个问题。

顺便说一句,我检查了我的类在 ApplicationContext 中扩展了 Abstract 类,但 Spring 没有看到我的自定义限定符

最佳答案

终于找到答案了。对于那些不明白这个问题的人。

我有一个带有方法 foo() 的接口(interface),然后是一个实现该接口(interface)并具有自己的抽象方法的抽象类

abstract class FooAbs impl Inter{
@Override
void foo(){
childMethod();
}
protected void childMethod();
}

最后我用 @Component 扩展了 FooAbs 类。

@Component 
class First extends FooAbs{

@Override
void childMethod(){}
}

问题出在动态代理上。

下面的代码无法从类获取接口(interface)

Proxy.newProxyInstance(beanClass.getClassLoader(), beanClass.getInterfaces(), (proxy, method, args) -> {}

动态代理看不到 First 类的 getInterfaces ,因为该类没有直接实现接口(interface),因此我将类签名更改为:

@Component 
class First extends FooAbs implement Inter{

@Override
void childMethod(){}
}

此步骤之后

beanClass.getInterfaces()

看到Inter界面。我知道这是一种解决方法,我将重写我的代码以避免这种结构。但它确实有效,也许对某些人会有帮助

关于java - 无法通过限定符注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50811357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com