循环依赖导致@Async无法初始化Bean问题

  1. 不要在循环引用的bean里使用@async。2. 使用@Lazy解决循环依赖导致无法初始化的问题

本质上:@Async的后置处理器,没有在getEarlyRefrence时,创建被@Async修饰代理对象,而是在initlizeBean方法中创建了代理对象。作为对比,被@Aspect修饰的Aop对象会在getEarlyRefrence阶段,提前创建代理对象,顾aop时不存在该问题

1、前奏:我在distPlanService中定义了一个异步方法,采用@Async注解。

2、异常:org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'deviceParamsManagerController': Unsatisfied dependency expressed through field 'deviceParamsManagerService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'deviceParamsManagerService': Unsatisfied dependency expressed through field 'deviceParamsValueManagerService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'deviceParamsValueManagerService': Unsatisfied dependency expressed through field 'remoteControlService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'remoteControlServiceImpl': Unsatisfied dependency expressed through field 'distPlanService'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'distPlanService': Bean with name 'distPlanService' has been injected into other beans [versionSpPackageService,distPlanTaskServiceImpl,adUpgradeService,versionMainService,adStrategyPackageService] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.

3、看第2点,搜索distPlanService关键字看红色比标注,解释是:创建名称为“distPlanService”的 bean 时出错:名称为“distPlanService”的 Bean 已作为循环引用的一部分被注入到其原始版本中的其他 bean [versionSpPackageService,distPlanTaskServiceImpl,adUpgradeService,versionMainService,adStrategyPackageService]

4、在看下图:


如此就找到了原因:distPlanService和versionSpPackageService有互相注入(@Autowired)

5、@Async解释:

spring从3开始提供了@Async注解,此注解可以被标注在方法或类上。案例中,标注在了方法上,以此代表该方法在被调用者调用时无语等待该方法的返回而继续执行调用处以下的代码逻辑,异步方法的实际执行将提交给Spring TaskExecutor的任务中,由指定的线程池中的线程执行。

6、循环依赖:

7、解释:

如果B(versionSpPackageService)注入了A(distPlanService),A注入了B, 此时A中增加一个异步方法(被@Async标注的方法),此时重启项目导致报错:前因后果,需要去分析源码,这里我用别人总结的话简单说一下:

        1.context.getBean(A)开始创建A,A实例化完成后给A的依赖属性b开始赋值
        2.context.getBean(B)开始创建B,B实例化完成后给B的依赖属性a开始赋值
        3.重点:此时因为A支持循环依赖,所以会执行A的getEarlyBeanReference方法得到它的早期引用。而执行getEarlyBeanReference()的时候因为@Async根本还没执行,所以最终返回的仍旧是原始对象的地址
        4.B完成初始化、完成属性的赋值,此时属性field持有的是Bean A原始类型的引用
        5.完成了A的属性的赋值(此时已持有B的实例的引用),继续执行初始化方法initializeBean(...),在此处会解析@Aysnc注解,从而生成一个代理对象,所以最终exposedObject是一个代理对象(而非原始对象)最终加入到容器里
        6.尴尬场面出现了:B引用的属性A是个原始对象,而此处准备return的实例A竟然是个代理对象,也就是说B引用的并非是最终对象(不是最终放进容器里的对象)
        7.执行自检程序:由于allowRawInjectionDespiteWrapping默认值是false,表示不允许上面不一致的情况发生,最终就抛错了。

8、我的解决方法:

(1)重新建class,把@Async的方法放在新的类中,从根本上消除循环依赖

(2) 也有其他方法,我并没有去验证:例如:采用@Lazy或者使用setter注入:在A注入B

  private VersionSpPackageService b;
    public void setB(VersionSpPackageService  b) {
        this.b = b;
    }

B注入A也是如此。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容