spring 循环依赖源码(spring源码系列七)

一、前言

上一篇我们分析了spring属性是如何注入的,但是如果bean与bean之间存在循环依赖怎么处理?

二、案例

如:X引用了Y,Y引用了X;

@Component public class X { @Autowired Y y; public X(){ System.out.println("X create"); } }

@Component public class Y { @Autowired X x; public Y(){ System.out.println("Y create"); } }

上面2个类就是我们常常说的循环依赖;

我们也可以通过在AnnotationConfigApplicationContext的初始化的时候加了一行setAllowCircularReferences(false); 这样就将spring的循环依赖给关闭了;

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Test.class); context.setAllowCircularReferences(false); context.refresh();

那么为什么setAllowCircularReferences(false);会关闭循环依赖呢?首要明白spring的循环依赖是怎么做到的呢?spring源码当中是如何处理循环依赖的? 分析一下所谓的循环依赖其实无非就是属性注入,而属性注入我们上一篇分析了,算是为这一篇进行铺垫的吧;

三、源码分析

我们从之前的属性注入那里分析吧,入口方法:org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { /** 验证bean的合法性 */ String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. /** 判断这个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); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. /** 判断是在一个正在被创建的原型集合中 */ if (isprototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. /** 判断实例化之前是否有需要依赖实例化的类 */ String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" beanName "' and '" dep "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" beanName "' depends on missing bean '" dep "'", ex); } } } // Create bean instance. /** 判断是否单列 */ if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { /** 创建bean */ return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a Prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean '" beanName "'"); } Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" scopeName "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" scopeName "' is not active for the current thread; consider " "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" name "' to required type '" ClassUtils.getQualifiedName(requiredType) "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }

其中第一个getSingleton方法会判断这个bean是否有被创建,刚刚开始的时候其实不会走下面这个逻辑;

因为如果是X进行实例化,X是第一次走这个方法,所以没有在创建中,后续会添加进去;

protected Object getSingleton(String beanName, boolean allowEarlyReference) { // Quick check for existing instance without full singleton lock /** 一级缓存:从单例池中获取 */ Object singletonObject = this.singletonObjects.get(beanName); /** * 如果为空则判断bean是否正在被创建 * 判断是否在singletonsCurrentlyInCreation正在创建的集合中 */ if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { /** 二级缓存:获取半成品bean */ singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { synchronized (this.singletonObjects) { // Consistent creation of early reference within full singleton lock /** 一级缓存:再次获取,防止线程安全问题 */ singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { /** 二级缓存:获取半成品bean */ singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null) { /** 三级缓存 */ ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { /** 获取半成品bean */ singletonObject = singletonFactory.getObject(); /** 放入二级缓存 */ this.earlySingletonObjects.put(beanName, singletonObject); /** 删除三级缓存中的数据 */ this.singletonFactories.remove(beanName); } } } } } } return singletonObject; }

而第二个getSingleton方法最主要的是判断是否在创建中,如果没有则加入singletonsCurrentlyInCreation集合中,这个集合很重要,后面循环依赖处理会使用到;上面第一个getSingleton方法判断是否在创建中也是判断是否加入了singletonsCurrentlyInCreation集合中;

判断完之后则调用入参的函数中的createBean方法;

spring 循环依赖源码(spring源码系列七)(1)

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) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" beanName "'"); } /** * 判断bean是否被排除,并且是否在创建的过程中 * 如果是的则将标识设置为true */ beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { /** 调用之前入参的那个函数 */ singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }

protected void beforeSingletonCreation(String beanName) { /** 判断是否被排除并且加入singletonsCurrentlyInCreation正在创建的集合是否成功 */ if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } }

createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" beanName "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. /** 获取类 */ Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. /** aop相关:找出所有相关的aop通知 */ Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { /** 具体创建bean的逻辑 */ Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" beanName "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }

doCreateBean

这个方法很重要,里面包含了循环依赖的逻辑,如果支持循环依赖,并且正在创建中就添加到集合singletonFactories和registeredSingletons中;

如果你想判断那些bean是被注册的可以通过registeredSingletons集合去判断,目前不需要关心;

是否正在创建就是判断是否在singletonsCurrentlyInCreation集合中,上面有讲解,bean会先放入这个集合才会继续往下走;

后面则是属性填充,属性填充上一篇分析过了,其实就是根据名称和类型去查找,找到了再根据getBean实例化出来,调用getBean时其实走的就是当前我们这一套逻辑;

如:X进行实例化,因为引用了Y,所以实例化时在属性填充的时候会将Y找出来进行实例化;

但是实例化Y的时候X正在实例化,这时就需要分析一下spring是如何对这种循环依赖进行处理了;

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; /** 判断是否为单列 */ if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } /** 如果为空则创建对象 */ if (instanceWrapper == null) { /** * 推断构造方法、创建对象 */ instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. /** * 是否支持循环依赖 * 1、是否为单列 * 2、allowCircularReferences:是否开启循环依赖,默认为true * 3、是否正在被创建 */ 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)); } // Initialize the bean instance. Object exposedObject = bean; try { /** 属性填充 */ populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" beanName "' has been injected into other beans [" StringUtils.collectionToCommaDelimitedString(actualDependentBeans) "] 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."); } } } } // Register bean as disposable. try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }

public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); }

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); } } }

getSingleton

spring循环依赖的处理其实在第一个getSingleton方法里有进行处理,如果是处理中则会先去一个个缓存中去获取,都没有的话就会去三级缓存singletonFactories集合中获取一个工厂类,通过工厂类获取到一个半成品bean;

为什么是一个半成品的bean呢?因为此时X其实还在进行属性注入,只不过属性注入的时候需要先实例化Y,而Y又引用了X,所以Spring会先通过工厂类先将ban成品bean先给到Y进行注入,等Y走完了生命周期就会再去走X的生命周期,一般是没有什么问题的,只要你不在Y的生命周期回调中使用到X就好了;

但是如果我们对这个bean做了一个aop代理,此时就可能X的生命周期没有走完我们就去使用X了,其实这个AOP对其工厂类做了一个扩展,所以三级缓存中放的是一个工厂类,方便后续进行扩展,后续会分析AOP时会详细讲解;

此时三级缓存的数据就到了二级缓存去了,那二级缓存的数据后续是如何处理到一级缓存中去的呢,也就是我们的单例池singletonObjects,这个后续分析bean缓存阶段/生存期再进行讲解;

protected Object getSingleton(String beanName, boolean allowEarlyReference) { // Quick check for existing instance without full singleton lock /** 一级缓存:从单例池中获取 */ Object singletonObject = this.singletonObjects.get(beanName); /** * 如果为空则判断bean是否正在被创建 * 判断是否在singletonsCurrentlyInCreation正在创建的集合中 */ if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { /** 二级缓存:获取半成品bean */ singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { synchronized (this.singletonObjects) { // Consistent creation of early reference within full singleton lock /** 一级缓存:再次获取,防止线程安全问题 */ singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { /** 二级缓存:获取半成品bean */ singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null) { /** 三级缓存 */ ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { /** 获取半成品bean */ singletonObject = singletonFactory.getObject(); /** 放入二级缓存 */ this.earlySingletonObjects.put(beanName, singletonObject); /** 删除三级缓存中的数据 */ this.singletonFactories.remove(beanName); } } } } } } return singletonObject; }

Spring 循环依赖总结
  1. 三级缓存 registeredSingletons 对于我看来作用主要是用来:作为一个早期对象的暴露,他可能是一个代理工厂,也可能是一个原始对象,这里具体取决于上下文场景。
  2. 二级缓存 earlySingletonObjects 作为一个不完整的对象来暴露,此时对象没有完成属性的赋值,但是它里面的的对象可以作为自动注入的对象,注入给使用者。
  3. 一级缓存 singletonObjects 存放的一个完整的对象,标志单实例 Bean 已经完成创建。
,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页