@Transactional使自定义注解失效

Posted tommaoxiaoqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@Transactional使自定义注解失效相关的知识,希望对你有一定的参考价值。

问题背景:

要添加@Transactional注解,使某功能可以原子操作。

接口调用结构:controller->processor(类似Service层)->flow(类似Manager层)

附:推荐的工程结构:

1. 请求处理:(Web层)控制转发

2. 业务逻辑(Service层)具体业务逻辑

3.通用处理 (Manager层)service能力下沉,缓存,三方平台,与DAO交互。

4.数据持久(DAO层)数据访问,与mysql交互。

调用过程:

controller到processor之间是通过统一的接口分发。

所有的processor都有自定义注解,里面存接口url路径名。启动时通过ApplicationContext.getBeansOfType()把所有processor注册到一个map里。注册时getAnnocation判断自定义注解不为空,把其中的接口名作为key,真实的processor作为value。

controller收到请求,转发给统一接口,统一的接口通过收到的url接口名,从map里找到对应的processor转发。processor直接调对应的flow。

 

问题现象:

在processor的方法上加@Transactional注解。此时调不到对应的processor。

调试发现,在启动注册时,该processor里就没有注册进来,根据url在map里自然找不到对应的processor。没注册进来发生在clazz.getAnnocation时候得到的为空。

从IOC容器中获取所有processor的bean的时候,获取到了所有processor。但是在含有@Transaction注解的那个processor在获得自定义注解内容的时候获取不到。

所以是@Transaction使通过getAnnotation()获取自定义注解失效。

 

产生原因:

@Transaction 的原理是AOP代理,从而使IOC中的bean是代理类,不是真实bean。自定义注解并没有继承过来,所以在代理类上找不到自定义注解。

 

解决方法:

1. 自定义注解在声明的时候加上 @Inherited,表明该注解是可以被子类继承的。父类有该注解子类也可以获取该注解。对类的继承有效,对接口的继承和实现无效。所以注意使用该方法的前提是AOP的动态代理使用的cglib而不是JDK自带的动态代理。

cglib是支撑基于类的动态代理,而JDK自带的是基于接口的动态代理。 使用cglib配置  <aop:aspectj-autoproxy proxy-target-class="true"/>

2. 将@Transaction下沉到flow层。最简单也最合理。

3. 可先通过AOP的代理类获取原始类,再通过原始类去获取注解。

先判断是不是Advised的实例。所有AOP代理的类都可以转型为Advised接口,可通过它找到原始类。 instanceof Advised。通过 getTargetSource()  getTarget() getClass() 获取到原始类。https://blog.csdn.net/u011403655/article/details/52259566

 

由此可见虽然只在一个方法上加了@Transaction注解,但整个类都会被AOP代理。

 

为什么只有加@Transaction注解使自定义注解失效,而原先方法上的其他注解却没有影响到自定义注解?

@Transaction使用的是AOP的动态代理生成的代理类,其他注解不是AOP。

常见的AOP注解如:@Aspect,@Before,@After,@Around,@Transaction。

 

若将@Transaction放到其他类如Controller的方法上,原始类的其他注解如@GetMapping并没有失效,功能正常。是否不用getAnnotation就不影响注解的功能?

 

以上是关于@Transactional使自定义注解失效的主要内容,如果未能解决你的问题,请参考以下文章

springboot+springcache+shiro+Redis整合时@Cacheable@Transactional等注解失效的问题

(转载)@Transactional spring 事务失效

java笔记java中@Transactional注解的使用及其失效情景

@Transactional注解失效

一口气说出 6种@Transactional注解的失效场景

一口气说出 6种,@Transactional注解的失效场景