问题:什么是循环依赖呢? 就是一个或者多个bean之间互相引用对方,这种依赖关系最终形成一个闭环就是循环依赖。循环依赖有这以下几种情况:自己依赖自己 两个对象互相依赖 多个对象间接依赖 问题:循环依赖有几种场景呢?构造器注入publicclassA{privateBb;通过构造方法注入BpublicA(Bb){System。out。println(bb);}publicvoidtest(){System。out。println(属性Bb);}}publicclassB{privateAa;通过构造方法注入ApublicB(Aa){System。out。println(aa);}publicvoidtest(){System。out。println(属性Aa);}}xml配置beanclasscom。gongj。circularDependencies。dto。Aidaconstructorargindex0refbconstructorargbeanbeanclasscom。gongj。circularDependencies。dto。Bidbconstructorargindex0refaconstructorargbean复制代码启动类publicstaticvoidmain(String〔〕args){ClassPathXmlApplicationContextcontextnewClassPathXmlApplicationContext(circularDependencies。xml);Aa(A)context。getBean(a);a。test();}结果:抛出BeanCreationException异常复制代码单例的setter注入publicclassA{privateBb;publicBgetBb(){returnb;}publicvoidsetBb(Bb){this。bb;}publicvoidtest(){System。out。println(属性Bb);}}publicclassB{privateAa;publicAgetAa(){returna;}publicvoidsetAa(Aa){this。aa;}publicvoidtest(){System。out。println(属性Aa);}}xml配置:beanclasscom。gongj。circularDependencies。dto。Aidapropertynamebbrefbpropertybeanbeanclasscom。gongj。circularDependencies。dto。Bidbpropertynameaarefapropertybean结果:属性Bcom。gongj。circularDependencies。dto。B19d37183复制代码dependson指定依赖beanclasscom。gongj。circularDependencies。dto。Aidadependsonbpropertynamebbrefbpropertybeanbeanclasscom。gongj。circularDependencies。dto。Bidbdependsonapropertynameaarefapropertybean结果:抛出BeanCreationException异常复制代码原型的setter注入beanclasscom。gongj。circularDependencies。dto。Aidascopeprototypepropertynamebbrefbpropertybeanbeanclasscom。gongj。circularDependencies。dto。Bidbscopeprototypepropertynameaarefapropertybean结果:抛出BeanCreationException异常复制代码 从上面的几个例子可以得知: 对于构造器的循环依赖,Spring是无法自动帮我们解决的,会抛出BeanCurrentlyInCreationException异常,表示循环依赖。当然可以由我们程序员解决,下面会讲到的。 Spring帮我们解决的循环依赖是单例的settet注入的循环依赖。对于作用域为prototype的循环依赖,Spring也是不会解决的,直接抛出BeanCurrentlyInCreationException异常。 使用dependson属性指定依赖,造成循环依赖,Spring也不会对此进行解决,直接抛出BeanCurrentlyInCreationException异常。 那么循环依赖是个问题吗?如果不考虑Spring,循环依赖并不是问题,因为对象之间相互依赖是很正常的事情。那在Spring中为什么会有循环依赖这种问题产生呢?那是因为在Spring中,一个对象并不是简单new出来的,而是会经过一系列的Bean的生命周期,就是因为Bean的生命周期所以才会出现循环依赖问题。当然,在Spring中,出现循环依赖的场景很多,有的场景Spring帮我们解决了,而有的场景则需要程序员来解决,下文详细来说Spring是如何解决循环依赖的,也就是为什么允许单例的setter循环依赖注入。Bean的生命周期 这里不会对Bean的生命周期进行详细的描述,只描述一下大概的过程。想详细了解可以看看笔者前面的源码阅读。如果想真正的理解循环依赖,那对Bean的生命周期肯定要有了解的。 Bean的生命周期指的就是:在Spring中,Bean是如何生成的? Bean的生成步骤如下: 可以看到,对于Spring中的Bean的生成过程,步骤很多。 但可以发现,在Spring中,创建一个Bean,是在实例化这步得到的。推断构造方法之后根据构造方法反射得到一个对象的,当然还有其他方式得到一个对象,比如说工厂方法、Supplier回调,不管其他方式如何创建,反正创建对象出来的这一步叫实例化,而创建出来的这个对象我们称之为原始对象! 得到一个原始对象后,Spring需要给对象中的属性进行依赖注入,那么这个注入过程是怎样的? 比如上文说的A类,A类中存在一个B类的b属性,所以,当A类生成了一个原始对象之后,就会去给b属性去赋值,此时就会根据b属性的类型和属性名(beanName)去BeanFactory中去获取B类所对应的单例bean。如果此时BeanFactory中存在B对应的Bean,那么直接拿来赋值给b属性;如果此时BeanFactory中不存在B对应的Bean,则需要生成一个B对应的Bean,然后赋值给b属性。 问题就出现在第二种情况,如果此时B类在BeanFactory中还没有生成对应的Bean,那么就需要去生成,就会经过B的Bean的生命周期。 那么在创建B类Bean的过程中,B类中存在一个A类的a属性,那么在创建B类Bean的过程中就需要A类对应的Bean,B类就会去创建A,所以这里就出现了循环依赖: ABean创建依赖了B属性触发BBean创建B依赖了A属性需要ABean(但ABean还在创建过程中) 从而导致ABean创建不出来,BBean也创建不出来。 简化一下生命周期,将重要的部分列出来:A的生命周期1。实例化A对象(newA()),称之为原始对象2。填充b属性(走getBean流程)从单例池中获取对应的bean找不到创建B对应的Bean(走B的生命周期)3。填充其他属性4。初始化后5。添加单例池B的生命周期1。实例化B对象(newB()),称之为原始对象2。填充a属性(走getBean流程)从单例池中获取对应的bean找不到创建A对应的Bean(走A的生命周期)3。填充其他属性4。初始化后5。添加单例池复制代码 这就是循环依赖,但是上文说了,Spring通过某些机制帮开发者解决了单例setter注入循环依赖的问题,这个机制就是三级缓存。问题:什么是三级缓存? Spring使用三级缓存解决循环依赖!singletonObjects:一级缓存,用于保存经历了完整生命周期的bean对象,也就是成品对象,最终给程序员使用的对象。earlySingletonObjects:二级缓存,比singletonObjects多了一个early,early早期,用于保存实例化完成的bean实例,Bean的生命周期还没走完就把这个Bean实例放入了earlySingletonObjects中,属于半成品对象。singletonFactories:三级缓存,缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的。主要是解决SpringAOP。问题:一定要三级缓存吗? 就上述出现的循环依赖,一定要用三级缓存才能解决吗?再增加一个Map不就解决了吗?一个缓存用于存放成品对象,另外一个缓存用于存放半成品对象。没有AOP的循环依赖 A的生命周期1。实例化A对象(newA()),称之为原始对象原始对象放入gongJMap中进行缓存2。填充b属性(走getBean流程)从单例池中获取b对应的bean找不到创建B对应的Bean(走B的生命周期)3。填充其他属性4。初始化后5。添加单例池B的生命周期1。实例化B对象(newB()),称之为原始对象原始对象放入gongJMapb,B原始对象中进行缓存2。填充a属性(走getBean流程)从单例池中获取a对应的bean找不到去gongJMap获取得到A原始对象3。填充其他属性4。初始化后5。添加单例池复制代码 可以看到二级缓存就能解决上述的循环依赖(不进行AOP时)。那Spring为什么要使用三级缓存呢?其实主要是4。初始化后这步会可能进行AOP操作。AOP操作会根据你的原始对象产生一个代理对象。生命周期再次发生变化,需要进行AOPA的生命周期1。实例化A对象(newA()),称之为原始对象原始对象放入gongJMap中进行缓存2。填充b属性(走getBean流程)从单例池中获取b对应的bean找不到创建B对应的Bean(走B的生命周期)3。填充其他属性4。初始化后(AOP)产生代理对象5。添加单例池B的生命周期1。实例化B对象(newB()),称之为原始对象原始对象放入gongJMapb,B原始对象中进行缓存2。填充a属性(走getBean流程)从单例池中获取a对应的bean找不到去gongJMap获取得到A原始对象3。填充其他属性4。初始化后(AOP)产生代理对象5。添加单例池复制代码 各位可以思考一下上面这个步骤有没有问题?1。实例化A对象(newA()),称之为原始对象原始对象放入gongJMap中进行缓存2。填充b属性(走getBean流程)从单例池中获取b对应的bean找不到创建B对应的Bean(走B的生命周期)3。实例化B对象(newB()),称之为原始对象原始对象放入gongJMapb,B原始对象中进行缓存4。填充a属性(走getBean流程)从单例池中获取a对应的bean找不到去gongJMap获取得到A原始对象5。填充其他属性6。初始化后(AOP)产生代理对象7。添加单例池(将B代理对象放到单例池)B生命周期结束走A的生命周期A的b属性放的是B的代理对象8。填充其他属性9。初始化后(AOP)产生代理对象10。添加单例池(将A代理对象放到单例池)复制代码 在第4步进行填充a属性拿到的是A的原始对象。而在第2步填充b属性,A里的b属性放的是B的代理对象。造成两者不一致了,正常情况需如下: A的b属性填充的是B的代理对象,B的a属性填充的是A的代理对象。这才是正常的。那怎么解决呢!终于需要用到三级缓存了吗?不不不,还用不到,在这里还是可以使用二级解决的。办法:提前进行AOP处理,然后在初始化后那步进行判断,如果进行过AOP操作就不再进行AOP了。A的生命周期1。实例化A对象(newA()),称之为原始对象提前进行AOP,产生代理对象放入gongJMap中进行缓存2。填充b属性(走getBean流程)从单例池中获取b对应的bean找不到创建B对应的Bean(走B的生命周期)3。填充其他属性4。初始化后(AOP),判断是否进行过AOP了4。5从gongJMap获取A的代理对象5。添加单例池(A代理对象)B的生命周期1。实例化B对象(newB()),称之为原始对象提前进行AOP,产生代理对象放入gongJMapb,B代理对象中进行缓存2。填充a属性(走getBean流程)从单例池中获取a对应的bean找不到去gongJMap获取得到A代理对象3。填充其他属性4。初始化后(AOP),判断是否进行过AOP了4。5从gongJMap获取B的代理对象5。添加单例池(B代理对象)复制代码 这种方式解决了A、B对象属性不一致的问题。那这里就会出现一个新的问题,什么情况下才需要提前进行AOP呢?答案是产生循环依赖的时候才需要提前进行AOP。因为如果没有出现循环依赖,A、B两个Bean各自走自己的生命周期那是不会有影响的。A的生命周期1。实例化A对象(newA()),称之为原始对象原始对象放入gongJMap中进行缓存2。填充属性3。初始化后(AOP)产生A代理对象4。添加单例池(A代理对象)B的生命周期1。实例化B对象(newB()),称之为原始对象原始对象放入gongJMapb,B原始对象中进行缓存2。填充属性3。初始化后(AOP)产生B代理对象4。添加单例池(B代理对象)复制代码 那又会有一个问题,我要才能怎么知道你产生了循环依赖呢?还是上述例子,A依赖B,B依赖A。在创建A的时候能知道有循环依赖吗?那肯定不能!填充b属性的时候?不能!实例化B?不能。只有在B实例化之后进行a属性填充时,才能知道A、B发生了循环依赖。 解决:增加一个Set集合,用来存取正在创建的beanName。生命周期再次发生变化,如下:A的生命周期0。将a放入Set中1。实例化A对象(newA()),称之为原始对象2。填充b属性(走getBean流程)从单例池中获取b对应的bean找不到创建B对应的Bean(走B的生命周期)3。填充其他属性4。初始化后(AOP)4。5从gongJMap获取A的代理对象5。添加单例池(A代理对象)B的生命周期0。将b放入Set中1。实例化B对象(newB()),称之为原始对象2。填充a属性(走getBean流程)从单例池中获取a对应的bean找不到判断a是否正在创建中正在创建中,代表出现了循环依赖gongJMap寻找找不到进行AOP,产生代理对象得到A代理对象gongJMap中进行缓存3。填充其他属性4。初始化后(AOP)4。5从gongJMap获取B的代理对象5。添加单例池(B代理对象)复制代码 看到这,不知道各位有没有疑问,原始对象我们没有将它缓存起来了。但前面又讲过,代理对象需要根据原始对象去创建。所以这时候才需要用到第三级缓存了。A的生命周期0。将a放入Set中,标记为当前单例bean正在创建中1。实例化A对象(newA()),称之为原始对象放入第三级缓存beanName:A原始对象2。填充b属性(走getBean流程)从单例池中获取b对应的bean找不到判断b是否正在创建中(B没有在创建中)创建B对应的Bean(走B的生命周期)3。填充其他属性4。初始化后(AOP)4。5从gongJMap获取A的代理对象5。添加单例池(A代理对象)B的生命周期0。将b放入Set中,标记为当前单例bean正在创建中1。实例化B对象(newB()),称之为原始对象放入第三级缓存beanName:B原始对象2。填充a属性(走getBean流程)从单例池中获取a对应的bean找不到判断a是否正在创建中正在创建中,代表出现了循环依赖从gongJMap寻找找不到从第三级缓存寻找得到A原始对象进行AOP,产生代理对象得到A代理对象gongJMap中进行缓存3。填充其他属性4。初始化后(AOP)4。5从gongJMap获取B的代理对象5。添加单例池(B代理对象)复制代码 到此,Spring为什么要使用三级缓存去解决循环依赖的思路就到这了。接下来我们就开始阅读源码,看看Spring设计的是否与我们推断是否一致。源码阅读 源码阅读呢会涉及到几个方法。我们根据上述所说的Bean的生命周期来分析。第零步 该方法位于DefaultSingletonBeanRegistrygetSingleton(StringbeanName,ObjectFactorylt;?singletonFactory)。 创建A对象,首先从单例池拿,有直接返回。没有的话首先将A添加到正在创建Bean的集合中,然后进行创建A逻辑。publicObjectgetSingleton(StringbeanName,ObjectFactorylt;?singletonFactory){Assert。notNull(beanName,Beannamemustnotbenull);synchronized(this。singletonObjects){去单例池中获取实例ObjectsingletonObjectthis。singletonObjects。get(beanName);如果不存在实例,则创建单例bean实例if(singletonObjectnull){忽略把当前正在创建的beanName添加到singletonsCurrentlyInCreation中,singletonsCurrentlyInCreation是一个Set表示这些bean正常创建中,在没创建完时不能重复创建beforeSingletonCreation(beanName);booleannewSingletonfalse;booleanrecordSuppressedExceptions(this。suppressedExceptionsnull);if(recordSuppressedExceptions){this。suppressedExceptionsnewLinkedHashSet();}try{singletonFactory是外面传进来的lambda表达式,执行lambda表达式就是调用createBean()singletonObjectsingletonFactory。getObject();newSingletontrue;}忽略将创建好的单例bean添加到单例池singletonObjects中和单例注册表registeredSingletons中并清除二级、三级缓存if(newSingleton){addSingleton(beanName,singletonObject);}}returnsingletonObject;}}protectedvoidbeforeSingletonCreation(StringbeanName){inCreationCheckExclusions中的beanName,表示如果是这些bean正在创建中,重复创建也没关系singletonsCurrentlyInCreation中的beanName,表示这些bean正常创建中,在没创建完时不能重复创建if(!this。inCreationCheckExclusions。contains(beanName)!this。singletonsCurrentlyInCreation。add(beanName)){thrownewBeanCurrentlyInCreationException(beanName);}}复制代码第一步1。实例化A对象(newA()),称之为原始对象放入第三级缓存beanName,A原始对象复制代码 关注一下2、实例化,这里会产生一个原始对象。该方法位于AbstractAutowireCapableBeanFactory。protectedObjectdoCreateBean(finalStringbeanName,finalRootBeanDefinitionmbd,finalNullableObject〔〕args)throwsBeanCreationException{省略代码2、实例化if(instanceWrappernull){创建bean实例1、工厂方法2、构造函数自动注入3、简单初始化instanceWrappercreateBeanInstance(beanName,mbd,args);}包装的实例对象,也就是原始对象finalObjectbeaninstanceWrapper。getWrappedInstance();省略代码4、如果当前bean是单例并且支持循环依赖,且当前bean正在创建,就通过往singletonFactories(三级缓存)添加一个objectFactory,这样后期如果有其他bean依赖该bean可以从singletonFactories获取到bean,解决循环依赖getEarlyBeanReference()可以对返回的bean进行修改,这边目前除了可能会返回代理对象其他的都是直接返回beanbooleanearlySingletonExposure(mbd。isSingleton()this。allowCircularReferencesisSingletonCurrentlyInCreation(beanName));if(earlySingletonExposure){if(logger。isTraceEnabled()){logger。trace(EagerlycachingbeanbeanNametoallowforresolvingpotentialcircularreferences);}构造一个ObjectFactory添加到singletonFactories中addSingletonFactory(beanName,()getEarlyBeanReference(beanName,mbd,bean));}Initializethebeaninstance。ObjectexposedObjectbean;try{5、填充属性Autowired,将各个属性注入对bean进行填充将各个属性注入populateBean(beanName,mbd,instanceWrapper);6、执行初始化方法exposedObjectinitializeBean(beanName,exposedObject,mbd);}catch(Throwableex){if(exinstanceofBeanCreationExceptionbeanName。equals(((BeanCreationException)ex)。getBeanName())){throw(BeanCreationException)ex;}else{thrownewBeanCreationException(mbd。getResourceDescription(),beanName,Initializationofbeanfailed,ex);}}7、if(earlySingletonExposure){earlySingletonReference只有在检测到有循环依赖的情况下才会不为空ObjectearlySingletonReferencegetSingleton(beanName,false);if(earlySingletonReference!null){如果提前暴露的对象(bean)和经过了完整的生命周期后的对象相等(exposedObject)则把缓存中的earlySingletonReference赋值给exposedObject最终会添加到singletonObjects中去(初始化之后的bean等于原始的bean,说明不是proxy),if(exposedObjectbean){exposedObjectearlySingletonReference;}检测该bean的dependon的bean是否都已经初始化好了elseif(!this。allowRawInjectionDespiteWrappinghasDependentBean(beanName)){String〔〕dependentBeansgetDependentBeans(beanName);SetStringactualDependentBeansnewLinkedHashSet(dependentBeans。length);for(StringdependentBean:dependentBeans){if(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)){actualDependentBeans。add(dependentBean);}}returnexposedObject;}复制代码 我们再关注一下第四点,该代码所处的位置Bean进行实例化之后,属性填充之前。按照我们的理解是要放入到三级缓存的。4、如果当前bean是单例并且支持循环依赖,且当前bean正在创建,就通过往singletonFactories(三级缓存)添加一个objectFactory,这样后期如果有其他bean依赖该bean可以从singletonFactories获取到bean,解决循环依赖getEarlyBeanReference()可以对返回的bean进行修改,这边目前除了可能会返回动态代理对象其他的都是直接返回beanbooleanearlySingletonExposure(mbd。isSingleton()this。allowCircularReferencesisSingletonCurrentlyInCreation(beanName));if(earlySingletonExposure){if(logger。isTraceEnabled()){logger。trace(EagerlycachingbeanbeanNametoallowforresolvingpotentialcircularreferences);}构造一个ObjectFactory添加到singletonFactories中addSingletonFactory(beanName,()getEarlyBeanReference(beanName,mbd,bean));}复制代码 要不要往三级缓存添加对象是由earlySingletonExposure这个变量控制的。三个值都为true时,earlySingletonExposure才为truembd。isSingleton():当前bean是单例allowCircularReferences:是否支持循环依赖,默认是trueisSingletonCurrentlyInCreation(beanName):当前bean是否正在创建中,创建中则返回true,至于在哪里被放入到Set集合中的,可以看前面的源码阅读。具体代码在DefaultSingletonBeanRegistry类的getSingleton方法。 earlySingletonExposure这个变量的值,正常情况下都是为true的。所以addSingletonFactory方法都会被执行,那一起来看看它干了什么? addSingletonFactory方法两个入参,一个是beanName,一个是类型为ObjectFactory的函数式接口。protectedvoidaddSingletonFactory(StringbeanName,ObjectFactorylt;?singletonFactory){Assert。notNull(singletonFactory,Singletonfactorymustnotbenull);synchronized(this。singletonObjects){if(!this。singletonObjects。containsKey(beanName)){this。singletonFactories。put(beanName,singletonFactory);this。earlySingletonObjects。remove(beanName);this。registeredSingletons。add(beanName);}}}复制代码 如果一级缓存singletonObjects,也就是单例池中不存在当前beanName的记录,则进入if代码块。首先往三级缓存singletonFactories中添加一个key为beanName,value为ObjectFactory的数据。然后从二级缓存earlySingletonObjects删除key为beanName的数据。再然后将beanName放入registeredSingletons的Set集合中。这段代码重点就是往第三级缓存里添加了一个key为beanName,value为ObjectFactory的函数式接口,也就是一个Lambda表达式。我们自己推断的只放一个原始对象。那我们来看看具体的Lambda表达式的实现!注意,这里并没有执行Lambda表达式的具体实现。可以看到这段代码比较符合我们所推测的,只不过Spring是往三级缓存里存的是类型为ObjectFactory的Lambda表达式而不是纯粹原始对象。第二步 2、然后进行b属性填充从单例池中获取b对应的bean找不到判断b是否正在创建中(B没有在创建中,还没开始创建呢)创建B对应的Bean。 最终会调用到getBean(beanName)方法。然后进入到doGetBean方法。protectedTTdoGetBean(finalStringname,NullablefinalClassTrequiredType,NullablefinalObject〔〕args,booleantypeCheckOnly)throwsBeansException{对name进行转换,找到真正的beanName如果传入的name是gongjFactoryBean,那么beanName就是gongjFactoryBeanfinalStringbeanNametransformedBeanName(name);Objectbean;根据beanName去单例池中获取BeanObjectsharedInstancegetSingleton(beanName);Mapif(sharedInstance!nullargsnull){if(logger。isTraceEnabled()){if(isSingletonCurrentlyInCreation(beanName)){logger。trace(ReturningeagerlycachedinstanceofsingletonbeanbeanNamethatisnotfullyinitializedyetaconsequenceofacircularreference);}else{logger。trace(ReturningcachedinstanceofsingletonbeanbeanName);}}判断sharedInstance是不是FactoryBean,如果是FactoryBean,那么真正需要拿到的是getObject方法所返回的对象beanName是spinrg进行解析后获取到的BeanNamename我们手动传入的beanNamesharedInstance根据beanName获取到的单例Bean对象beangetObjectForBeanInstance(sharedInstance,name,beanName,null);}单例池没有获取到Bean则走创建Bean的流程else{}复制代码 上述代码在本篇中只需要关注getSingleton方法。OverrideNullablepublicObjectgetSingleton(StringbeanName){returngetSingleton(beanName,true);}复制代码 注意getSingleton(beanName,true);的第二个参数值为true。NullableprotectedObjectgetSingleton(StringbeanName,booleanallowEarlyReference){从单例池中获取实例ObjectsingletonObjectthis。singletonObjects。get(beanName);如果从单例池中没有获取到实例并且指定的单例bean正在创建中if(singletonObjectnullisSingletonCurrentlyInCreation(beanName)){锁定全局变量并进行处理synchronized(this。singletonObjects){earlySingletonObjects二级缓存singletonObjectthis。earlySingletonObjects。get(beanName);没有从二级缓存中获取到并且allowEarlyReference为trueif(singletonObjectnullallowEarlyReference){实例化之后调用addSingletonFactory方法将ObjectFactory初始化存储在singletonFactoriesMap中singletonFactories三级缓存ObjectFactorylt;?singletonFactorythis。singletonFactories。get(beanName);if(singletonFactory!null){执行lambdaAOpsingletonObjectsingletonFactory。getObject();记录在缓存中earlySingletonObjects与singletonFactories互斥this。earlySingletonObjects。put(beanName,singletonObject);this。singletonFactories。remove(beanName);}}}}returnsingletonObject;}复制代码 从单例池获取bBean,那是肯定获取不到的,所以singletonObject值为null。至于b是否正在创建中,那肯定也是false,b还没开始创建!所以if代码块都不会进入,该方法直接返回null。返回null也就代表着B需要进行创建。进入到B的生命周期。第三步 开始创建BBean。流程如下:0。将b放入Set中,标记为当前单例bean正在创建中1。实例化B对象(newB()),称之为原始对象放入第三级缓存beanName:B原始对象2。填充a属性(走getBean流程)从单例池中获取a对应的bean找不到判断a是否正在创建中正在创建中,代表出现了循环依赖从gongJMap寻找找不到从第三级缓存寻找得到A原始对象进行AOP,产生代理对象得到A代理对象gongJMap中进行缓存复制代码单例池没有获取到Bean则走创建Bean的流程else{省略根据Scope去创建bean创建单例模式Bean的实例对象if(mbd。isSingleton()){使用一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象sharedInstancegetSingleton(beanName,(){try{returncreateBean(beanName,mbd,args);}catch(BeansExceptionex){Explicitlyremoveinstancefromsingletoncache:Itmighthavebeenputthereeagerlybythecreationprocess,toallowforcircularreferenceresolution。Alsoremoveanybeansthatreceivedatemporaryreferencetothebean。显式地从容器销毁给定的beandestroySingleton(beanName);throwex;}});sharedInstance可能是一个FactoryBean,如果是FactoryBean那么真正需要拿到的是getObject方法所返回的对象beangetObjectForBeanInstance(sharedInstance,name,beanName,mbd);}}复制代码 关注一下getSingleton(StringbeanName,ObjectFactorylt;?singletonFactory)方法,该方法与第零步一模一样。publicObjectgetSingleton(StringbeanName,ObjectFactorylt;?singletonFactory){Assert。notNull(beanName,Beannamemustnotbenull);synchronized(this。singletonObjects){去单例池中获取实例ObjectsingletonObjectthis。singletonObjects。get(beanName);如果不存在实例,则创建单例bean实例if(singletonObjectnull){忽略把当前正在创建的beanName添加到singletonsCurrentlyInCreation中,singletonsCurrentlyInCreation是一个Set表示这些bean正常创建中,在没创建完时不能重复创建beforeSingletonCreation(beanName);booleannewSingletonfalse;booleanrecordSuppressedExceptions(this。suppressedExceptionsnull);if(recordSuppressedExceptions){this。suppressedExceptionsnewLinkedHashSet();}try{singletonFactory是外面传进来的lambda表达式,执行lambda表达式就是调用createBean()singletonObjectsingletonFactory。getObject();newSingletontrue;}忽略将创建好的单例bean添加到单例池singletonObjects中和单例注册表registeredSingletons中并清除二级、三级缓存if(newSingleton){addSingleton(beanName,singletonObject);}}returnsingletonObject;}}复制代码 这里就会走B的生命周期了。进行实例化。singletonFactory是外面传进来的lambda表达式,执行lambda表达式就是调用createBean()singletonObjectsingletonFactory。getObject();复制代码 进行完B的实例化之后,然后进行填充属性。发现需要填充A属性,再走A的getBean方法。 既然是走getBean的方法,那就会进入到第二步所分析的getSingleton方法。NullableprotectedObjectgetSingleton(StringbeanName,booleanallowEarlyReference){从单例池中获取实例ObjectsingletonObjectthis。singletonObjects。get(beanName);如果从单例池中没有获取到实例并且指定的单例bean正在创建中if(singletonObjectnullisSingletonCurrentlyInCreation(beanName)){锁定全局变量并进行处理synchronized(this。singletonObjects){earlySingletonObjects二级缓存singletonObjectthis。earlySingletonObjects。get(beanName);没有从二级缓存中获取到并且allowEarlyReference为trueif(singletonObjectnullallowEarlyReference){实例化之后调用addSingletonFactory方法将ObjectFactory初始化存储在singletonFactoriesMap中singletonFactories三级缓存ObjectFactorylt;?singletonFactorythis。singletonFactories。get(beanName);if(singletonFactory!null){执行lambdaAOpsingletonObjectsingletonFactory。getObject();记录在缓存中earlySingletonObjects与singletonFactories互斥this。earlySingletonObjects。put(beanName,singletonObject);this。singletonFactories。remove(beanName);}}}}returnsingletonObject;}复制代码 从单例池获取aBean那是也是获取不到的,所以singletonObject值为null。至于a是否正在创建中,a现在是在创建中了,所以进入if代码块,从二级缓存中获取实例,肯定获取不到,所以为null,至于allowEarlyReference的值,由上层传入true。然后从三级缓存根据beanName(也就是a)获取到ObjectFactory类型的一个函数式接口。这时候是有值的,我们在A实例化之后,就将key为a的ObjectFactory接口放入到了三级缓存中了。然后调用singletonFactory的getObject(),也就是执行lambda体。我们现在可以知道lambda体是在产生循环依赖的时候才会被执行。然后将获得的对象保存在二级缓存中,将三级缓存的记录进行删除。 lambda体执行完毕之后,会返回一个对象。那该对象一定是代理对象吗? 执行lambda体,也技术执行getEarlyBeanReference方法。进入AbstractAutowireCapableBeanFactory类getEarlyBeanReference方法,protectedObjectgetEarlyBeanReference(StringbeanName,RootBeanDefinitionmbd,Objectbean){ObjectexposedObjectbean;if(!mbd。isSynthetic()hasInstantiationAwareBeanPostProcessors()){for(BeanPostProcessorbp:getBeanPostProcessors()){AOPif(bpinstanceofSmartInstantiationAwareBeanPostProcessor){SmartInstantiationAwareBeanPostProcessoribp(SmartInstantiationAwareBeanPostProcessor)bp;exposedObjectibp。getEarlyBeanReference(exposedObject,beanName);}}}returnexposedObject;}复制代码 先将原始对象赋予给另外一个变量。获得所有的BeanPostProcessor,判断是否是SmartInstantiationAwareBeanPostProcessor,如果是则执行getEarlyBeanReference方法。将原始对象和bean名称作为入参传入。 调试进入SmartInstantiationAwareBeanPostProcessor类,可以发现getEarlyBeanReference方法下有两个子类实现。一个是InstantiationAwareBeanPostProcessorAdapter,另外一个是AbstractAutoProxyCreator。这里我们看AbstractAutoProxyCreator就好了,因为InstantiationAwareBeanPostProcessorAdapter没有进行具体的实现。 进入AbstractAutoProxyCreator类,其实这时候我们可以发现该类所处的包路径为 org。springframework。aop。framework。autoproxy;,可以看到一个眼熟的词aop。获取提前暴露的bean的引用,用来支持单例对象的循环引用,解决循环依赖问题OverridepublicObjectgetEarlyBeanReference(Objectbean,StringbeanName){ObjectcacheKeygetCacheKey(bean。getClass(),beanName);this。earlyProxyReferences。put(cacheKey,bean);returnwrapIfNecessary(bean,beanName,cacheKey);可能会产生代理对象}复制代码 该方法里有三行代码,我们一行一行的看。getCacheKeyprotectedObjectgetCacheKey(Classlt;?beanClass,NullableStringbeanName){if(StringUtils。hasLength(beanName)){isAssignableFrom:判断当前的Class所表示的类,是不是参数中传递的Class所表示的类的父类,超接口,或者是相同的类型是则返回true,否则返回false使用方式:父类。class。isAssignableFrom(子类。class)return(FactoryBean。class。isAssignableFrom(beanClass)?BeanFactory。FACTORYBEANPREFIXbeanName:beanName);}else{returnbeanClass;}}复制代码 首先判断当前beanName不等于null并且不等于空字符串,然后使用三元表达式计算当前beanClass是否是FactoryBean子类或者子实现,如果是则将beanName拼接上。 第二行往earlyProxyReferencesMap容器里添加了一条记录,key为cacheKey的值,value为原始对象。在生命周期初始化后那步就会根据earlyProxyReferencesMap进行判断,是否进行过AOP。 接下来我们看最重要的一个方法:wrapIfNecessary,方法名翻译之后大意是如果需要包装,也就是说,如果要包装则产生代理对象,否则返回原对象。是否要产生代理对象是有条件的。wrapIfNecessaryprotectedObjectwrapIfNecessary(Objectbean,StringbeanName,ObjectcacheKey){在当前targetSourcedBeans中存在的bean,表示在实例化之前就产生了代理对象直接返回,那就不要再次产生代理对象了if(StringUtils。hasLength(beanName)this。targetSourcedBeans。contains(beanName)){returnbean;}advisedBeans是一个map,存储的是class:是否应该被代理,为true则需要被代理当前这个bean不用被代理if(Boolean。FALSE。equals(this。advisedBeans。get(cacheKey))){returnbean;}如果是普通bean,或者继承Advisor、Pointcut、AdviceAopInfrastructureBean的类不需要被代理if(isInfrastructureClass(bean。getClass())shouldSkip(bean。getClass(),beanName)){将当前cacheKey标记为不用被代理this。advisedBeans。put(cacheKey,Boolean。FALSE);returnbean;}获取当前beanClass所匹配的advisorsObject〔〕specificInterceptorsgetAdvicesAndAdvisorsForBean(bean。getClass(),beanName,null);如果匹配的advisors不等于null,那么则进行代理,并返回代理对象if(specificInterceptors!DONOTPROXY){将当前cacheKey标记为需要被代理this。advisedBeans。put(cacheKey,Boolean。TRUE);基于bean对象和Advisor创建代理对象ObjectproxycreateProxy(bean。getClass(),beanName,specificInterceptors,newSingletonTargetSource(bean));存一个代理对象的类型this。proxyTypes。put(cacheKey,proxy。getClass());returnproxy;}this。advisedBeans。put(cacheKey,Boolean。FALSE);returnbean;}复制代码 上面AOP的逻辑走完了之后,就会将A对象进行返回,然后赋值给B。B的属性填充也就此完成,那就会继续往下走。if(earlySingletonExposure){earlySingletonReference只有在检测到有循环依赖的情况下才会不为空ObjectearlySingletonReferencegetSingleton(beanName,false);if(earlySingletonReference!null){如果提前暴露的对象(bean)和经过了完整的生命周期后的对象相等(exposedObject)则把缓存中的earlySingletonReference赋值给exposedObject最终会添加到singletonObjects中去(初始化之后的bean等于原始的bean,说明不是proxy),if(exposedObjectbean){exposedObjectearlySingletonReference;}检测该bean的dependon的bean是否都已经初始化好了elseif(!this。allowRawInjectionDespiteWrappinghasDependentBean(beanName)){String〔〕dependentBeansgetDependentBeans(beanName);SetStringactualDependentBeansnewLinkedHashSet(dependentBeans。length);for(StringdependentBean:dependentBeans){if(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)){actualDependentBeans。add(dependentBean);}}因为bean创建后;其所依赖的bean一定是创建了的。actualDependentBeans不为空表示当bean创建后依赖的bean没有全部创建完,也就是说存在循环依赖if(!actualDependentBeans。isEmpty()){thrownewBeanCurrentlyInCreationException(beanName,BeanwithnamebeanNamehasbeeninjectedintootherbeans〔StringUtils。collectionToCommaDelimitedString(actualDependentBeans)〕initsrawversionaspartofacircularreference,buthaseventuallybeenwrapped。Thismeansthatsaidotherbeansdonotusethefinalversionofthebean。ThisisoftentheresultofovereagertypematchingconsiderusinggetBeanNamesOfTypewiththeallowEagerInitflagturnedoff,forexample。);}}}}try{8、注册DisposableBeanregisterDisposableBeanIfNecessary(beanName,bean,mbd);}catch(BeanDefinitionValidationExceptionex){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,Invaliddestructionsignature,ex);}returnexposedObject;复制代码getSingleton:注意allowEarlyReference的值为false。NullableprotectedObjectgetSingleton(StringbeanName,booleanallowEarlyReference){从单例池中获取实例ObjectsingletonObjectthis。singletonObjects。get(beanName);如果从单例池中没有获取到实例并且指定的单例bean正在创建中if(singletonObjectnullisSingletonCurrentlyInCreation(beanName)){锁定全局变量并进行处理synchronized(this。singletonObjects){earlySingletonObjects二级缓存singletonObjectthis。earlySingletonObjects。get(beanName);没有从二级缓存中获取到并且allowEarlyReference为trueif(singletonObjectnullallowEarlyReference){实例化之后调用addSingletonFactory方法将ObjectFactory初始化存储在singletonFactoriesMap中singletonFactories三级缓存ObjectFactorylt;?singletonFactorythis。singletonFactories。get(beanName);if(singletonFactory!null){执行lambdaAOpsingletonObjectsingletonFactory。getObject();记录在缓存中earlySingletonObjects与singletonFactories互斥this。earlySingletonObjects。put(beanName,singletonObject);this。singletonFactories。remove(beanName);}}}}returnsingletonObject;}复制代码 又是这个方法,带大家再来看看这个方法。这个时候beanName还是为b,B的生命周期还没走完呢。从单例池获取》没有,b还在创建中,所以进入if,然后从二级里面获取》没有,allowEarlyReference由上层传入false,结束方法,返回null。返回null,就不会符合earlySingletonReference!null的判断,直接调用registerDisposableBeanIfNecessary方法,进行Bean销毁逻辑。protectedvoidregisterDisposableBeanIfNecessary(StringbeanName,Objectbean,RootBeanDefinitionmbd){AccessControlContextacc(System。getSecurityManager()!null?getAccessControlContext():null);if(!mbd。isPrototype()requiresDestruction(bean,mbd)){if(mbd。isSingleton()){RegisteraDisposableBeanimplementationthatperformsalldestructionworkforthegivenbean:DestructionAwareBeanPostProcessors,DisposableBeaninterface,customdestroymethod。registerDisposableBean(beanName,newDisposableBeanAdapter(bean,beanName,mbd,getBeanPostProcessors(),acc));}else{Abeanwithacustomscope。。。Scopescopethis。scopes。get(mbd。getScope());if(scopenull){thrownewIllegalStateException(NoScoperegisteredforscopenamembd。getScope());}scope。registerDestructionCallback(beanName,newDisposableBeanAdapter(bean,beanName,mbd,getBeanPostProcessors(),acc));}}}复制代码 只要看requiresDestruction方法就好了。protectedbooleanrequiresDestruction(Objectbean,RootBeanDefinitionmbd){判断某个Bean是否拥有销毁方法1。实现了DisposableBean接口或AutoCloseable接口2。BeanDefinition中定义了destroyMethodName3。类中是否存在PreDestroy注解的方法return(bean。getClass()!NullBean。class(DisposableBeanAdapter。hasDestroyMethod(bean,mbd)(hasDestructionAwareBeanPostProcessors()DisposableBeanAdapter。hasApplicableProcessors(bean,getBeanPostProcessors()))));}