spring中,当同一个类中两个方法互相调用时,@Transactional注解失效问题原理理解
spring中,当同一个类中两个方法互相调用时,@Transactional注解失效问题原理理解问题详述解决办法疑问学习和理解后记问题详述具体情况如下:我们使用spring容器进行bean管理时;我们使用spring进行事务管理也就是使用@Transactional;我们在同一个业务类中,不同的两个方法上都使用了@Transactional注解,一个记为方法A,另一个记为方法B;该业务类中的方法A
·
问题详述
具体情况如下:
- 我们使用spring容器进行bean管理时;
- 我们使用spring进行事务管理也就是使用@Transactional;
- 我们在同一个业务类中,不同的两个方法上都使用了@Transactional注解,一个记为方法A,另一个记为方法B;
- 该业务类中的方法A调用了方法B,且B中我们使用传播级别为无论如何都创建一个新的事务执行,且异常处理后不影响外层,也就是Propagation.NESTED;
- 结果发现被调用的方法B中的事务失效了,也就是部分成功提交,部分未成功执行;
解决办法
网上可以查到很多种,但一般我都用比较简单的一种:就是在该类中自动注入本类bean,使用@Autowired即可,然后使用这个注入的bean去调用本类方法,即可达到两方法事务都起效
疑问
- 查过上述解决办法的各种理解,感觉很迷;主要是说,直接调用同类方法使用的是this.xxx()的方式;这个说法没有任何问题。
- 问题是:自动注入的spring容器中的该类对象本来就是加强过的代理对象,那么this此时指代的不应该就是这个代理对象吗,那么调用到的为什么不是增强过的对象的方法呢?
- 或者说,代理对象其实是在每次调用时才产生的?实际存在于容器中的还是原始对象?
学习和理解
针对问题3:看了spring书中的aop方面的介绍,代理对象生成是bean后处理器处理的,那么很明显,就是在容器初始化的时候生成的代理对象了(前提:我们使用的是ApplicationContext的这个子容器,而不是BeanFactory这个最原始的容器,一般都是用的前者);因为bean后处理器的处理时机是紧跟着bean的初始化结束后的。也就是说,容器中存储的就已经是增强结束的代理对象了,而不是原始对象!
针对问题2:从动态代理的原理出发可以发现问题:
- 其实代理对象维护着一个原始对象的引用,在执行代理对象的增强方法时,只是在使用原始对象调用原始方法的前后,去执行了一些增强操作。也就是说,实际上,还是要调用原始对象的原始方法,而且使用的就是原始对象。
- 那也就清晰了,因为在调用增强方法时,也就是增强方法A时;先执行了执行前的增强,再用原始对象去调用方法A的;然后在方法A中调用方法B,所以这里的this指向的就是原始对象;而非增强对象!!!那么一切就能够合理解释了。
后记
有写得不对的地方欢迎探讨。。。
更多推荐
已为社区贡献1条内容
所有评论(0)