场景:业务需要要在类上面加上自定义注解,在项目启动时去获取这个注解进行下一步的操作,结果在添加自定义注解的类中有方法加上了@sync注解,并在springboot的启动类上加上了@EnableAsync,开启了异步,导致该类被动态代理,自定义注解获取失败。
过程:因为之前遇到过类似问题,一开始以为cglib动态代理,就在自定义注解上加了@Inherited,该注解的作用是继承,就是说继承该类的子类会获取到该类的自定义注解。结果发现加了@sync注解的类被jdk动态代理了,这就有问题了。cglib动态代理是生成一个原类的子类,而JDK动态代理只能对实现了接口的类生成代理,而不能针对类。也就是说cglib动态代理是生产一个原类的儿子,JDK动态代理是生成一个原类的兄弟。这就造成自定义注解加了@Inherited也无效。
获取注解的方法是: XXX.getClass().getAnnotation(自定义注解.class);
解决:首先想到的是让项目指定cglib动态代理,别用JDK动态代理。配置方式是在springboot的yml文件中配置如下:
spring:
aop:
proxy-target-class: true
但是并没有什么用,加了@sync的类依然使用JDK动态代理,以为异步必须要JDK动态代理来实现,后来一想不能啊,cglib肯定可以,然后就在开启异步的注解源码中看到如下,这个异步默认是JDK动态代理,必须要把proxyTargetClass=true才能用cglib动态代理。
最后在启动类上修改为@EnableAsync(proxyTargetClass=true),完美解决!