【有料】深入理解Spring循环依赖

所谓循环依赖指的是:BeanA对象的创建依赖于BeanB,BeanB对象的创建也依赖于BeanA,这就造成了死循环,如果不做处理的话势必会造成栈溢出。Spring通过提前曝光机制,利用三级缓存解决循环依赖问题。本节将记录单实例Bean的创建过程,并且仅记录两种常见的循环依赖情况:普通Bean与普通Bean之间的循环依赖,普通Bean与代理Bean之间的循环依赖。

Bean创建源码

我们先通过源码熟悉下Bean创建过程(源码仅贴出相关部分)。

IOC容器获取Bean的入口为AbstractBeanFactory类的getBean方法:

1
2
3
4
5
6
7
8
9
10
11
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    ......

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    ......
}

该方法是一个空壳方法,具体逻辑都在doGetBean方法内:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    ......

    protected <T> T doGetBean(
            String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
            throws BeansException {

        // 获取Bean名称
        String beanName = transformedBeanName(name);
        Object bean;

        // 从三级缓存中获取目标Bean实例
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            ......

            // 不为空,则进行后续处理并返回
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        } else {
            ......

            try {
                ......
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                ......

                // 从三级缓存中没有获取到Bean实例,并且目标Bean是单实例Bean的话
                if (mbd.isSingleton()) {

                    // 通过getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法创建Bean实例
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            // 创建Bean实例
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            ......
                        }
                    });
                    // 后续处理,并返回
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                ......
            }
            catch (BeansException ex) {
                ......
            }
            finally {
                ......
            }
        }
        ......
        return (T) bean;
    }

    ......

}

doGetBean方法中先通过getSingleton(String beanName)方法从三级缓存中获取Bean实例,如果不为空则进行后续处理;如果为空,则通过getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法创建Bean实例并进行后续处理。

这两个方法都是AbstractBeanFactory父类DefaultSingletonBeanRegistry的方法,AbstractBeanFactory层级关系图如下所示:

getSingleton(String beanName)相关源码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    ......

    @Override
    @Nullable
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

    ......

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 从一级缓存中获取目标Bean实例
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果从一级缓存中没有获取到,并且该Bean处于正在创建中的状态时
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 从二级缓存获取目标Bean实例
            singletonObject = this.earlySingletonObjects.get(beanName);
            // 如果没有获取到,并且允许提前曝光的话
            if (singletonObject == null && allowEarlyReference) {
                synchronized (this.singletonObjects) {
                    // 在锁内重新从一级缓存中往下查找
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            // 从三级缓存中取出目标Bean工厂对象
                            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                // 工厂对象不为空,则通过调用getObject方法实例化Bean实例
                                singletonObject = singletonFactory.getObject();
                                // 放到二级缓存中
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                // 删除对应的三级缓存
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }
        return singletonObject;
    }

    ......

所谓的三级缓存指的是DefaultSingletonBeanRegistry类的三个成员变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    /** Cache of singleton objects: bean name to bean instance. */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** Cache of singleton factories: bean name to ObjectFactory. */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    /** Cache of early singleton objects: bean name to bean instance. */
    private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

    ......

}

变量描述
singletonObjects一级缓存,key为Bean名称,value为Bean实例。这里的Bean实例指的是已经完全创建好的,即已经经历实例化->属性填充->初始化以及各种后置处理过程的Bean,可直接使用。
earlySingletonObjects二级缓存,key为Bean名称,value为Bean实例。这里的Bean实例指的是仅完成实例化的Bean,还未进行属性填充等后续操作。用于提前曝光,供别的Bean引用,解决循环依赖。
singletonFactories三级缓存,key为Bean名称,value为Bean工厂。在Bean实例化后,属性填充之前,如果允许提前曝光,Spring会把该Bean转换成Bean工厂并加入到三级缓存。在需要引用提前曝光对象时再通过工厂对象的getObject()方法获取。

如果通过三级缓存的查找都没有找到目标Bean实例,则通过getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    ......

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        synchronized (this.singletonObjects) {
            // 从一级缓存获取
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                // 为空则继续
                ......
                // 方法内会将当前Bean名称添加到正在创建Bean的集合(singletonsCurrentlyInCreation)中
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                ......
                try {
                    // 通过函数式接口创建Bean实例,该实例已经经历实例化->属性填充->初始化以及各种后置处理过程,可直接使用
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                   ......
                }
                finally {
                    ......
                }
                if (newSingleton) {
                    // 添加到缓存中
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            // 添加到一级缓存
            this.singletonObjects.put(beanName, singletonObject);
            // 删除对应的二三级缓存
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }

    ......

}

上述代码重点关注singletonFactory.getObject(),singletonFactory是一个函数式接口,对应AbstractBeanFactory的doGetBean方法中的lambda表达式:

1
2
3
4
5
6
7
8
9
 sharedInstance = getSingleton(beanName, () -> {
    try {
        // 创建Bean实例
        return createBean(beanName, mbd, args);
    }
    catch (BeansException ex) {
        ......
    }
});

重点关注createBean方法。该方法为抽象方法,由AbstractBeanFactory子类AbstractAutowireCapableBeanFactory实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    ......
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        ......

        try {
            // 创建Bean实例
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            ......
        }
    }
    ......
}

doCreateBean源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    ......
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        BeanWrapper instanceWrapper = null;
        
        ......
        // 实例化Bean
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        Object bean = instanceWrapper.getWrappedInstance();
        
        ......

        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    // 执行MergedBeanDefinitionPostProcessor类型后置处理器
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    ......
                }
            }
        }

        // 如果该Bean是单例,并且allowCircularReferences属性为true(标识允许循环依赖的出现)以及该Bean正在创建中
        // 的话,earlySingletonExposure就为true,标识允许单实例Bean提前暴露原始对象引用(仅实例化)
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            // 添加到单实例工厂集合中,即三级缓存对象,该方法第二个参数类型为ObjectFactory<?> singletonFactory,
            // 前面提到过,它是一个函数式接口,这里用lambda表达式() -> getEarlyBeanReference(beanName, mbd, bean)表示
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        Object exposedObject = bean;
        try {
            // 属性赋值操作
            populateBean(beanName, mbd, instanceWrapper);
            // 初始化Bean(初始化操作主要包括xxxxAware注入,BeanPostProcessor后置处理器方法调用以
            // 及InitializingBean接口方法调用,感兴趣的可以自己查看源码)
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            ......
        }

        // 如果earlySingletonExposure为true
        if (earlySingletonExposure) {
            // 第二个参数为false表示仅从一级和二级缓存中获取Bean实例
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    // 如果从一级和二级缓存中获取Bean实例不为空,并且exposedObject == bean的话,
                    // 将earlySingletonReference赋值给exposedObject返回
                    exposedObject = earlySingletonReference;
                }
                ......
            }
        }

        ......
        // 返回最终Bean实例
        return exposedObject;
    }
    ......

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            // SmartInstantiationAwareBeanPostProcessor类型后置处理,常见的场景为AOP代理
            for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
                exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
        return exposedObject;
    }
}

addSingletonFactory方法为父类DefaultSingletonBeanRegistry的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    ......
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        synchronized (this.singletonObjects) {
            // 一级缓存没有目标Bean实例的话,添加三级缓存
            if (!this.singletonObjects.containsKey(beanName)) {
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    }
    ......
}

上述整个过程可以用下图来总结(可右键选择新标签页中打开图片):

 

光看源码有点抽象,下面我们通过两个场景来加深理解。

普通Bean与普通Bean

首先模拟普通Spring Bean与普通Spring Bean之间循环依赖的场景。

新建SpringBoot项目,pom引入如下依赖:

1
2
3
4
5
6
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>

新建CircularReferenceTest类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class CircularReferenceTest {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanA.class, BeanB.class);
        BeanA beanA = context.getBean(BeanA.class);
        BeanB beanB = context.getBean(BeanB.class);
        BeanB beanBInBeanA = beanA.getBeanB();
        BeanA beanAInBeanB = beanB.getBeanA();
        System.out.println(beanA);
        System.out.println(beanB);
        System.out.println(beanB == beanBInBeanA);
        System.out.println(beanA == beanAInBeanB);
    }
}

class BeanA {

    @Autowired
    private BeanB beanB;

    public BeanB getBeanB() {
        return beanB;
    }

    public void setBeanB(BeanB beanB) {
        this.beanB = beanB;
    }
}

class BeanB {

    @Autowired
    private BeanA beanA;

    public BeanA getBeanA() {
        return beanA;
    }

    public void setBeanA(BeanA beanA) {
        this.beanA = beanA;
    }
}

上面代码通过AnnotationConfigApplicationContext创建了IOC容器,并先后注册了BeanA和BeanB,BeanA和BeanB相互依赖,程序输出如下:

1
2
3
4
cc.mrbird.BeanA@368f2016
cc.mrbird.BeanB@6f03482
true
true

可以看到,Spring成功解决了循环依赖。下面配合源码来分析这个过程。

上面程序中,先创建BeanA,Spring内部调用doGetBean方法获取BeanA。一开始三级缓存中肯定没有BeanA和BeanB相关实例:

所以我们直接看doCreateBean相关源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    ......
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        BeanWrapper instanceWrapper = null;
        
        ......
        // 实例化BeanA,BeanA的早期对象,属性还未赋值,还未进行后置处理
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        Object bean = instanceWrapper.getWrappedInstance();
        
        ......

        // BeanA是单例对象,并且allowCircularReferences为true,BeanA正在创建中,所以
        // 最终earlySingletonExposure为true
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            // 将BeanA早期对象传递给Bean工厂,并添加到三级缓存中
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        Object exposedObject = bean;
        try {
            // 属性赋值操作
            populateBean(beanName, mbd, instanceWrapper);
            ......
        }
        ......
    }
    ......
}

上面代码,Spring实例化了BeanA,然后往三级缓存中添加了BeanA的工厂对象,根据前面getEarlyBeanReference方法的源码我们可以知道,在不存在AOP代理的情况下,该方法直接返回原始BeanA对象。所以通过该工厂方法创建的BeanA对象仅仅是进行了实例化操作,属性还未被赋值,换句话说,该工厂用于提前曝光BeanA实例。

接着调用populateBean方法对BeanA属性赋值,赋值过程发现BeanA依赖于BeanB,所以Spring重复以上步骤创建BeanB。创建过程中同样会遇到populateBean方法对BeanB属性赋值,赋值过程中发现BeanB依赖于BeanA,于是Spring又回头创建BeanA,不过这时候情况就开始不一样了!!

doGetBean方法内部从三级缓存中获取BeanA对象时,三级缓存内容如下:

可以看到一级缓存和二级缓存没有什么不一样,但三级缓存中已经存在BeanA和BeanB的工厂对象了!

所以此时getSingleton(String beanName, boolean allowEarlyReference)方法内的逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    ......

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        // 一级缓存中没有BeanA,并且BeanA正在创建中
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            // 二级缓存中也没有BeanA
            if (singletonObject == null && allowEarlyReference) {
                synchronized (this.singletonObjects) {
                    // 在锁内重新从一级缓存中往下查找
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            // 从三级缓存中取出目标BeanA的工厂对象
                            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                // 工厂对象不为空,调用getObject方法获取前面提前曝光的BeanA早期实例
                                singletonObject = singletonFactory.getObject();
                                // 将BeanA早期实例放到二级缓存中
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                // 删除对应的三级缓存
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }
        // 返回BeanA早期实例
        return singletonObject;
    }

    ......

此时查看二级缓存:

可以看到,BeanA确实只是早期实例,属性BeanB还未被赋值呢。

随后BeanB在属性填充的时候获取到了BeanA早期实例,完成属性填充、初始化等后续操作,BeanB创建完毕。BeanB完整创建完毕后,BeanA随之也完成属性填充、初始化等后续操作,BeanA也创建完毕,循环依赖得以解决。

BeanB虽然获取到的是BeanA的早期对象,但当BeanA完整创建完毕后,BeanB里的BeanA也将会是完整的,因为指针指向的都是同一个BeanA地址。

画个图总结上面的过程(可右键选择新标签页中打开图片):

普通Bean与代理Bean

普通Bean和代理Bean之间的循环依赖和上面过程差不多,不过细节上有些许差异。

删除上面创建的CircularReferenceTest类。为了模拟AOP代理的情况,我们需要引入AOP依赖:

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后修改Boot入口类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
        BeanA beanA = context.getBean(BeanA.class);
        BeanB beanB = context.getBean(BeanB.class);
        BeanB beanBInBeanA = beanA.getBeanB();
        BeanA beanAInBeanB = beanB.getBeanA();
        System.out.println("BeanA是否为代理对象:" + AopUtils.isAopProxy(beanA));
        System.out.println("BeanB是否为代理对象:" + AopUtils.isAopProxy(beanB));
        System.out.println("beanAInBeanB是否为代理对象:" + AopUtils.isAopProxy(beanAInBeanB));
        System.out.println(beanB == beanBInBeanA);
        System.out.println(beanA == beanAInBeanB);
    }
}

@Component
class BeanA {

    @Autowired
    private BeanB beanB;

    public BeanB getBeanB() {
        return beanB;
    }

    public void setBeanB(BeanB beanB) {
        this.beanB = beanB;
    }
}

@Component
class BeanB {

    @Autowired
    private BeanA beanA;

    public BeanA getBeanA() {
        return beanA;
    }

    public void setBeanA(BeanA beanA) {
        this.beanA = beanA;
    }
}

@Aspect
@Component
class MyAspect {

    @Pointcut("execution(public * cc.mrbird.BeanA.getBeanB())")
    public void pointcut() {

    }
    @Before("pointcut()")
    public void onBefore(JoinPoint joinPoint) {
        System.out.println("onBefore:" + joinPoint.getSignature().getName() + "方法开始执行");
    }

}

因为MyAspect切面类的存在,BeanA将会是个代理类,而BeanB则是普通Bean,程序输出如下:

1
2
3
4
5
6
onBefore:getBeanB方法开始执行
BeanA是否为代理对象:true
BeanB是否为代理对象:false
beanAInBeanB是否为代理对象:true
true
true

假设容器先创建BeanA,过程和上面的例子一致,属性填充时,发现BeanA依赖BeanB,然后Spring开始创建BeanB。创建BeanB时候又发现其依赖BeanA,这时三级缓存中已经存在BeanA的工厂对象了,所以直接通过该工厂对象获取BeanA的早期实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    ......

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        // 一级缓存中没有BeanA,并且BeanA正在创建中
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            // 二级缓存中也没有BeanA
            if (singletonObject == null && allowEarlyReference) {
                synchronized (this.singletonObjects) {
                    // 在锁内重新从一级缓存中往下查找
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            // 从三级缓存中取出目标BeanA的工厂对象
                            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                // 工厂对象不为空,调用getObject方法获取前面提前曝光的BeanA早期实例
                                singletonObject = singletonFactory.getObject();
                                // 将BeanA早期实例放到二级缓存中
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                // 删除对应的三级缓存
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }
        // 返回BeanA早期实例
        return singletonObject;
    }

    ......

singletonFactory.getObject()实际实现为lambda表达式() -> getEarlyBeanReference(beanName, mbd, bean),getEarlyBeanReference方法源码:

1
2
3
4
5
6
7
8
9
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
            exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
        }
    }
    return exposedObject;
}

在引入AOP依赖后,容器中将会有一个SmartInstantiationAwareBeanPostProcessor接口的实现类AbstractAutoProxyCreator,用于创建AOP代理,所以上面getEarlyBeanReference方法里的bp.getEarlyBeanReference(exposedObject, beanName)逻辑实际上为AbstractAutoProxyCreator实现的getEarlyBeanReference方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) {
        // 生成缓存Key
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 放入earlyProxyReferences集合中,标识BeanA为早期代理对象
        this.earlyProxyReferences.put(cacheKey, bean);
        // 在这个例子中,BeanA将被包装为代理对象
        return wrapIfNecessary(bean, beanName, cacheKey);
    }

}

所以BeanB从三级缓存中获取到的为代理后的BeanA实例:

BeanB创建完毕后,BeanA属性填充操作随之结束。

通过深入理解Spring-AOP原理对AOP的学习我们知道,代理对象是在后置处理BeanPostProcessor的postProcessAfterInitialization方法内完成的,而该方法的调用时机为Bean属性填充后的初始化操作时,所以在BeanA属性填充操作结束时,BeanA还只是一个普通对象,而BeanB里的BeanA已经是代理对象了。

继续BeanA的创建过程,BeanA属性填充完后,执行initializeBean(beanName, exposedObject, mbd)方法进行初始化操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    ......
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        ......
        Object exposedObject = bean;
        try {
            // 属性赋值操作
            populateBean(beanName, mbd, instanceWrapper);
            // 初始化操作
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        ......
    }
    ......
}

我们主要关注初始化操作阶段执行动态代理的后置处理方法过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    ......

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // 在BeanB填充属性时,BeanA已经被放入到earlyProxyReferences集合中了
            // 所以该if不成立,直接跳过,避免二次代理
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        // 所以这里返回的还是BeanA原始对象,并非代理对象
        return bean;
    }
    ......

到这里BeanA依旧是普通对象,继续查看doCreateBean方法的后续逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    ......
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        ......
        // 原始BeanA赋值给exposedObject
        Object exposedObject = bean;
        try {
            // 属性赋值操作
            populateBean(beanName, mbd, instanceWrapper);
            // 初始化操作,通过上面分析,此时返回的还是原始的BeanA对象
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        ......
        if (earlySingletonExposure) {
            // 从缓存中获取BeanA,此时二级缓存中已经存在BeanA的代理对象了,所以
            // 这里earlySingletonReference为BeanA的代理对象(如下图)
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                // exposedObject和bean相等,因为BeanA并未在初始化的时候被二次代理
                if (exposedObject == bean) {
                    // 这里将代理对象BeanA赋值给exposedObject
                    exposedObject = earlySingletonReference;
                }
                ......
            }
        }
        ......
        // 最终返回的exposedObject对象为从二级缓存中获取到的BeanA代理对象
        return exposedObject;
    }
    ......
}

到这里,无论是BeanB里的BeanA,还是IOC容器中的BeanA,都是代理后的BeanA了。

画张图总结下上面的过程(可右键选择新标签页中打开图片):

总结

上面的例子都是基于属性注入的情况,假如存在构造器注入情况下的循环依赖,Spring将没办法解决。这是因为对象的提前曝光时机发生在对象实例化之后,而构造器注入时机为对象实例化时,所以此时还未进行提前曝光操作,循环依赖也就没办法解决了,比如下面这种情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

@Component
class BeanA {

    private BeanB beanB;

    public BeanA(BeanB beanB) {
        this.beanB = beanB;
    }

    public BeanB getBeanB() {
        return beanB;
    }

    public void setBeanB(BeanB beanB) {
        this.beanB = beanB;
    }
}

@Component
class BeanB {

    private BeanA beanA;

    public BeanB(BeanA beanA) {
        this.beanA = beanA;
    }

    public BeanA getBeanA() {
        return beanA;
    }

    public void setBeanA(BeanA beanA) {
        this.beanA = beanA;
    }
}

程序将抛出如下异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  beanA defined in file [/Users/mrbird/idea workspace/aop-deep-learn/target/classes/cc/mrbird/BeanA.class]
↑     ↓
|  beanB defined in file [/Users/mrbird/idea workspace/aop-deep-learn/target/classes/cc/mrbird/BeanB.class]
└─────┘

此外,这里讨论了普通Bean与普通Bean之间的循环依赖,代理Bean与普通Bean之间的循环依赖,实际情况还可能存在工厂Bean与普通Bean、代理Bean之间的循环依赖,这种情况比较复杂,本文不讨论,因为就理解Spring解决循环依赖的思想而言,上面两种情况搞清楚了就OK了。

转自:深入理解Spring循环依赖 | MrBird

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值