Spring中Bean循环依赖详解

1. Bean创建的主要流程

先获取,没有的话再创建,如下图所示

Spring中Bean循环依赖详解_第1张图片

 创建bean的主要流程如下:

  • getSingleton:从容器里面获取单例的bean,没有的话创建
  • doCreateBean:没有就创建bean
  • addSIngletonFactory:将创建bean的 factory 缓存起来
  • populateBean:创建完了以后,要填充属性
  • addSingleton:填充完了以后,再添加到容器进行使用

依赖是在目标对象里,代理对象的字段没有值,如下图所示:

Spring中Bean循环依赖详解_第2张图片

2. 解决循环依赖时需要的缓存

Spring在解决循环依赖时使用了 三级缓存,如果没有代理的话,用一级缓存就可以解决。二三级缓存主要是为了解决代理的生成。

一级缓存(也叫单例池): singletonObjects,存放已经经历了完整生命周期的Bean对象。

二级缓存: earlySingletonObjects,存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完整),存放半成品的Bean。

三级缓存: singletonFactories,存放可以生成Bean的工厂,主要是解决aop特性,()->getEarlyBeanReference(beanName,mbd,bean),getEarlyBeanReference()返回增强后的bean。

3. 循环依赖具体流程分析

在代码中创建3个Bean,然后相互依赖,再创建切面,让这几个Bean生成代理。

3.1 代码示例

@Component
public class TestA {

    @Autowired
    TestB testB;

    public void test(){
        System.out.println("----aaa----");
    }
}
@Component
public class TestB {

    @Autowired
    TestC testC;

    public void test(){
        System.out.println("----bbb----");
    }
}
@Component
public class TestC {

    @Autowired
    TestA testA;

    public void test(){
        System.out.println("----ccc----");
    }
}

@Aspect
@Configuration
public class TestAspect {


    @Pointcut("execution(* com.shopping.demo24.component.*.test(..))")
    public void pointcut() {}

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println(this.getClass().getSimpleName()+"-around:before");
        Object result=joinPoint.proceed();
        System.out.println(this.getClass().getSimpleName()+"-around:after");
        return result;
    }

}

3.2 调试分析

1. 获取a->创建a->将a添加到singletonFactories->设置依赖b->获取b

Spring中Bean循环依赖详解_第3张图片

2. 创建b->将b添加到singletonFactories->设置依赖c开始->获取c

3.创建c->将c添加到singletonFactories

此时缓存池中的 bean 如下,没有写的为空

singletonFactories:a, b, c

Spring中Bean循环依赖详解_第4张图片

 4. 给c设置依赖a开始->获取a

先从singletonObjects中获取,没有,再从earlySingletonObjects中获取,也没有,最后在singletonFactories的ObjectFactory中获取。获取以后添加到earlySingletonObjects中,这里面的a是增强后的a,但是依赖的属性没有设置。再从singletonFactories中删除

此时

earlySingletonObjects: a

singletonFactories: b,c

Spring中Bean循环依赖详解_第5张图片

 ObjectFactory的值为 () -> getEarlyBeanReference(beanName, mbd, bean)

 从ObjectFactory获取时会对a调用BeanPostProcessor的getEarlyBeanReference()返回增强后的a

Spring中Bean循环依赖详解_第6张图片

 Spring中Bean循环依赖详解_第7张图片

 包装对象,生成代理

Spring中Bean循环依赖详解_第8张图片

 a 在这里增强后,在后面的postProcessAfterInitialization()方法中,创建代理对象(增强对象)的AbstractAutoProxyCreator中如果有对应的earlyProxyReferences记录(这里的记录不是增强对象,而是原始对象),就不会再被增强。

Spring中Bean循环依赖详解_第9张图片

 Spring中Bean循环依赖详解_第10张图片

 5. 通过反射,给c设置依赖

Spring中Bean循环依赖详解_第11张图片

给c设置依赖a结束,调用initializeBean()方法,生成代理对象,创建完c,将c添加到singletonObjects中,删除earlySingletonObjects和singletonFactories中的对应值。

Spring中Bean循环依赖详解_第12张图片

 此时

earlySingletonObjects:a

singletonFactories: b

singletonObjects: c

6: 给b设置依赖c结束,调用initializeBean()方法,生成代理对象, 创建完b,将b添加到singletonObjects中b是代理对象

earlySingletonObjects:a

singletonFactories: null

singletonObjects: b,c

7: 给a设置依赖b完成

此时,对于 a, 调用initializeBean()方法返回的不是增强对象,

Spring中Bean循环依赖详解_第13张图片

 Spring中Bean循环依赖详解_第14张图片

因为earlyProxyReferences中存在a,表示它已经被增强过

Spring中Bean循环依赖详解_第15张图片

 获取earlySingletonObjects中的a,这里的a是增强对象。

创建完a,将a添加到singletonObjects中

Spring中Bean循环依赖详解_第16张图片

earlySingletonObjects:null

singletonFactories: null

singletonObjects: b,c,a

至此,a,b,c 三个bean创建完成,也都加到了 singletonObjects 中,其他两个缓存池都为空。

你可能感兴趣的:(Spring,spring,java,spring,boot)