所谓循环依赖指的是: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了。