时间:2021-05-19
概述
在前面一篇文章中,介绍,在一个Bean中注入自己,如果有@Async和@Transaction,如果使用@Autowire注入自身,会报循环依赖,如果使用BeanFactoryAware注入自己,会使得@Transaction失效。 例如:
@Servicepublic class MyService implements BeanFactoryAware{ private MyService self; //事务注解无效 @Transactional public void notWork() { ... } @Async public Future async(){ ... } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { self= beanFactory.getBean(MyService.class); }}当时只是简单提了一下,这篇文章就是来介绍为什么会失效。
一般情况
造成上面的情况需要满足以下条件:
造成的结果:除@Async外的注解生效,其他的都不生效,如下图
而正常代理的应该是下图:
原因
首先想到的是@Async注解的处理方式可能和其他的不一样。在AsyncAnnotationBeanPostProcessor的实现中(具体代码是在其父类AbstractAdvisingBeanPostProcessor),发现一个问题,
正常情况下,进来的bean已经是被代理的动态代理类,而失效的时候,进来的确实实际的类,如下图:
然后在分析下代码,如果是实际的类,走到69行的时候,返回是true,把@Aysnc的Advisor加入到动态道理中,而如果是实际的类,走到83行的时候,就会创建代理类,只把@Aysnc的advisor加入到动态代理中,所已诸如@Transaction就会失效。
为什么进来的不是代理类
其实唯一的区别就是BeanFactoryAware中,是否通过了BeanFactory获取了自己。那为什么使用BeanFactory获取了自己,后续的BeanPostProcessor中就不是代理了?如果熟悉Spring @Transaction加载机制的就知道,诸如@Transaction,@Retryable 注解的动态代理创建是在AnnotationAwareAspectJAutoProxyCreator中创建的。通过debug发现,经过AnnotationAwareAspectJAutoProxyCreator后,我们的动态代理竟然没有加上。
再看一下AnnotationAwareAspectJAutoProxyCreator中的实现,但是经过他却没有生成代理类。原因竟然是提前暴露的Map里面竟然有“myService”,
他是什么时候暴露出来的呢?其实就是在
@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException { self= beanFactory.getBean(MyService.class);}那么,一切水落石出了,在实例MyService中,触发了BeanFactoryAware,通过beanFactory.getBean(MyService.class);中创建了代理类(tips:当前代理类并没有包含@Async的Adivisor),因为现在Spring其实正是在创建MyService这个Bean,还没有放入到BeanFactory中。然后我们再这个过程中又触发了一次beanFactory.getBean(MyService.class);导致创建代理并返回后,加入到了到了提前暴露的map中。导致后面的一系列问题。感觉有点绕。看图说话:
正常情况,应该是如下流程:
异常情况却是这样的
小结
正常情况下,还是使用@Autowire来注入把(如果使用Autowire,上述情况直接回抛出循环依赖)。当然,出现了问题,也是不能放过了,要知其然还要知其所以然!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
前言本文带你快速了解@Async注解的用法,包括异步方法无返回值、有返回值,最后总结了@Async注解失效的几个坑。在SpringBoot应用中,经常会遇到在一
Spring框架中@Autowired和@Resource注解的区别在spring框架中,除了使用其特有的注解外,使用基于JSR-250的注解,它包括@Post
Spring中有一个概念叫「元注解」(Meta-Annotation),通过元注解,实现注解的「派生性」,官方的说法是「AnnotationHierarchy」
Spring基于注解启动主要有两个Class实现注解启动AnnotationConfigApplicationContextAnnotationConfigWe
本文实例讲述了Spring的组合注解和元注解原理与用法。分享给大家供大家参考,具体如下:一点睛从Spring2开始,为了相应JDK1.5推出的注解功能,Spri