博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于Spring注解@Async引发其他注解失效
阅读量:4877 次
发布时间:2019-06-11

本文共 1934 字,大约阅读时间需要 6 分钟。

概述

在前面一篇文章中,介绍,在一个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);    }}

当时只是简单提了一下,这篇文章就是来介绍为什么会失效。

一般情况

造成上面的情况需要满足以下条件:

  1. 有@Async和其他类似@Transaction注解
  2. 自己类在BeanFactoryAware中,通过BeanFactory获取自己

造成的结果:除@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,上述情况直接回抛出循环依赖)。当然,出现了问题,也是不能放过了,要知其然还要知其所以然!

 

转载于:https://www.cnblogs.com/lizo/p/8652576.html

你可能感兴趣的文章
Introduction Sockets to Programming in C using TCP/IP
查看>>
PHP 简单实现webSocket
查看>>
zookeeper部署搭建
查看>>
navigationController pop回之前控制器
查看>>
汇编语言实验一
查看>>
Web.config配置文件详解(新手必看)
查看>>
selenide总结
查看>>
selenium--控制浏览器和简单元素操作
查看>>
android spannableString 替换 textview 中部分文字
查看>>
java 引用
查看>>
关于Spring注解@Async引发其他注解失效
查看>>
关于学习的一些感悟
查看>>
算法提高 概率计算
查看>>
UVa 12716 - GCD XOR(筛法 + 找规律)
查看>>
Spring Cloud学习资料
查看>>
制作无广告启动盘
查看>>
python使用httplib2访问REST服务的例子
查看>>
经典代码(01)
查看>>
生成ico格式图标
查看>>
并查集hdu4424
查看>>