gpt4 book ai didi

java - 为什么无法从beanClass获取注解?

转载 作者:行者123 更新时间:2023-11-30 02:38:34 24 4
gpt4 key购买 nike

@Transactional
@Component
@EntranceLog
public class TransferServiceImpl implements TransferService {

xxxx

}

我有一个带有 Transactional 注释和 Component 注释的类。 EntranceLog 是我自定义的通过aop打印日志的注解。

public class LogProxyCreator extends AbstractAutoProxyCreator implements ApplicationContextAware {

private static final LogInterceptor LOG = new LogInterceptor();

private static Logger log = LoggerFactory.getLogger(LogProxyCreator.class);

@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String s, TargetSource targetSource) throws BeansException {
Annotation anno = null;

for (Annotation annotationTemp : beanClass.getAnnotations()) {
Log temp = annotationTemp.annotationType().getAnnotation(EntranceLog.class);
if (temp != null) {
anno = temp;
break;
}
}

if (anno == null) {
return null;
}
Object[] additional = new Object[]{LOG};

log.error(beanClass.getName() + " has register the fc log.");

return additional;
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
LOG.setContext(applicationContext);
}
}

当我的应用程序启动时,bean TransferServiceImpl 启动,但 beanClass.getAnnotations() 无法获取任何注释。为什么?

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Log(logName = "entrance")
public @interface EntranceLog {
@AliasFor(
annotation = Log.class,
attribute = "subLogName"
)
String logName() default "";

@AliasFor(
annotation = Log.class,
attribute = "openInfoLog"
)
boolean openInfoLog() default false;
}

这是我的注释。

最佳答案

Spring @Transactional已经是 AOP 处理的注释,因此添加您自己的注释将需要一些额外的工作。让我解释一下 Spring AOP 和 @Transactional 是如何实现的有效。

Spring 有两种实现 AOP 的方式,如果类实现了接口(interface),它可以使用标准的 JDK 代理,如果类没有实现接口(interface),它将使用 CGLib 创建一个新的子类在运行时发出字节码。除非您非常小心,否则您几乎总是会使用 Spring AOP 获得 CGLib 代理。

当 Spring 遇到 @Transactional (类或方法级别)它使用 CGLib 创建一个新的子类,您可以将此类视为装饰器,它将所有调用转发到您的实现类。之前和之后(围绕建议)它检查 @Transactional注解属性,并检查线程本地存储以查看事务是否已存在,如果没有事务,则创建一个事务,并记住它,以便之后可以提交它。如果您在 Transactional 内设置断点方法并查看调用堆栈,您将看到对实现的调用来自装饰器类,并且没有其源代码。

在您的情况下,添加到应用程序上下文的 bean 不是您的 TransferServiceImpl bean,而是 Spring 在发现 @Transactional 时创建的 CGLib 代理您的类上的注释,它将被命名为 TransferServiceImpl$$FastClassBySpringCGLIB$$<hexstring> - 这个类没有@EntranceLog注释,这就是为什么你自己的方面不起作用。

我自己从未遇到过这个问题,因为我通常会尝试避免 AOP,或者总是在已经由 Spring 代理的 CGLib 类上避免 AOP。除非您想深入研究 Spring 源代码,或者找到 Spring 开发团队中的某人来帮助您完成此操作,否则我建议您创建另一层间接层,这样您就不需要在同一个类中处理两个方面。

关于java - 为什么无法从beanClass获取注解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42411642/

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