Spring的循环依赖 循环依赖有两种方式:构造函数参数循环依赖,以及属性循环依赖,构造函数参数循环依赖是没有办法解决的,所以我们常说的Spring解决的循环依赖一般指的是属性循环依赖。
Spring的循环依赖是通过建立三级缓存实现的 ,三级缓存主要是为了解决在AOP情况下,出现循环依赖的问题,当然,其中的一级+二级是为了解决读取不完整的性能问题,如果没了三级缓存,使用二级缓存也能够实现功能,但是会在每次创建Bean的时候调用动态代理的判断逻辑,影响性能问题。
1 2 3 4 5 6 7 8 9 10 11 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256 );private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16 );private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16 );
案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Component public class A { @Autowired public B b; public B getB () { return b; } public void setB (B b) { this .b = b; } public int div (int i, int j) { System.out.println("MathCalculator...div..." ); return i / j; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 @Service public class B { @Autowired private A a; public A getA () { return a; } public void setA (A a) { this .a = a; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Aspect @Component public class LogAspects { @Pointcut ("execution(public int spring.cricle.A.*(..))" ) public void pointCut () { } @Before ("pointCut()" ) public void logStart (JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); System.out.println("" + joinPoint.getSignature().getName() + "运行。。。@Before:参数列表是:{" + Arrays.asList(args) + "}" ); } }
1 2 3 4 5 @Configuration @EnableAspectJAutoProxy @ComponentScan ("spring.cricle" )public class Config {}
1 2 3 4 5 6 7 @Test public void test02 () { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class ) ; A a = context.getBean(A.class ) ; System.out.println(a.div(1 , 2 )); context.close(); }
可以看到上面的A.java
类和B.java
类是属性循环依赖的关系,并且A类被AOP
代理了,接下来分析一下怎么循环依赖的问题。
分析 摘取部分创建Bean
的源码上分析:
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 protected <T> T doGetBean ( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { String beanName = transformedBeanName(name); Object bean; Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null ) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null ); } else { if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } return (T) bean; }
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 public Object getSingleton (String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null" ); synchronized (this .singletonObjects) { Object singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null ) { try { singletonObject = singletonFactory.getObject(); newSingleton = true ; } catch (IllegalStateException ex) { } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
1 2 3 4 5 6 7 8 9 10 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); } }
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 protected Object doCreateBean (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (instanceWrapper == null ) { instanceWrapper = createBeanInstance(beanName, mbd, args); } boolean earlySingletonExposure = (mbd.isSingleton() && this .allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references" ); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false ); if (earlySingletonReference != null ) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } } } return exposedObject; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected void addSingletonFactory (String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null" ); synchronized (this .singletonObjects) { if (!this .singletonObjects.containsKey(beanName)) { this .singletonFactories.put(beanName, singletonFactory); this .earlySingletonObjects.remove(beanName); this .registeredSingletons.add(beanName); } } }
所以在给Bean
对象开辟内存空间,完成实例化之后,就会将该Bean对象存放在三级缓存singletonFactories
中。
然后才调用populateBean方法
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 protected void populateBean (String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { PropertyDescriptor[] filteredPds = null ; if (hasInstAwareBpps) { if (pvs == null ) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null ) { if (filteredPds == null ) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null ) { return ; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null ) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null ) { applyPropertyValues(beanName, mbd, bw, pvs); } }
通过跟踪上文AbstractAutowireCapableBeanFactory.postProcessProperties()
方法,想要给A类赋予B属性,就需要先创建B对象,最终它会调用来创建B对象。
1 2 3 4 5 public Object resolveCandidate (String beanName, Class<?> requiredType, BeanFactory beanFactory) throws BeansException { return beanFactory.getBean(beanName); }
B类的创建Bean
实例的逻辑和A类相同,因为B类也需要调用populateBean
给属性A赋值,在给A赋值的过程中,最终会重新回到上文中的resolveCandidate
调用beanFactory.getBean()
获取A对象的实例,接着进一步分析调用getBean()-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 protected <T> T doGetBean ( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { String beanName = transformedBeanName(name); Object bean; Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null ) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference" ); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'" ); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null ); } }
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 @Nullable protected Object getSingleton (String beanName, boolean allowEarlyReference) { Object singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { 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 ) { ObjectFactory<?> singletonFactory = this .singletonFactories.get(beanName); if (singletonFactory != null ) { singletonObject = singletonFactory.getObject(); this .earlySingletonObjects.put(beanName, singletonObject); this .singletonFactories.remove(beanName); } } } } } } return singletonObject; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 protected Object getEarlyBeanReference (String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; }
1 2 3 4 5 6 7 8 9 @Override public Object getEarlyBeanReference (Object bean, String beanName) { Object cacheKey = getCacheKey(bean.getClass(), beanName); this .earlyProxyReferences.put(cacheKey, bean); return wrapIfNecessary(bean, beanName, cacheKey); }
所以在这时候,就能够返回一个A类的动态代理对象,是在初始化B类,给B类开辟实例空间后,准备赋值属性A时,调用beanFactory.getBean(A)
时创建的。
当给B类的初始化成功后,最终会调用addSingleton()
方法,添加到一级缓存中,然后调用链将回到初始化实例的函数上,B的初始化是由于初始化A时,需要赋值A的属性B,才会被调度的。
这时候,当A初始化完成后,doCreateBean()
方法的第五步:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false ); if (earlySingletonReference != null ) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } } }
总结:
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 getBean(A) -> doGetBean(A) -> getSingleton(A) -> markBeanAsCreated(A) -> getSingleton(beanName, ObjectFactory<?>) -> ObjectFactory.createBean() -> doCreateBean(A) -> createBeanInstance() -> addSingletonFactory(beanName, singletonObject) -> populateBean() -> getBean(B) -> doGetBean(B) -> markBeanAsCreated(B) -> getSingleton(beanName, ObjectFactory<?>) -> createBean() -> doCreateBean(B) -> createBeanInstance() -> addSingletonFactory(beanName, singletonObject) -> populateBean() -> getBean(A) -> doGetBean(A) -> getSingleton(A) -> ObjectFactory.getEarlyBeanReference -> getEarlyBeanReference -> wrapIfNecessary(A) -> return proxyA -> applyPropertyValues() -> addSinleton(B) -> applyPropertyValues() -> getSingleton(beanName, false); -> if (exposedObject == bean) { exposeObject = proxyA} -> addSingleton(proxyA)
在没有添加动态代理的情况下,使用二级缓存就能解决循环依赖的问题,其调度过程如下图:
“本篇文章主要摘自参考资料 ”