一个对象依赖对象闭环到自己
A -> B -> .... ->A
tip:
不涉及代理对象问题
解决方法:当一个对象已经实例化完毕了,还未初始化的时候,将它注入到它所依赖的已经实例好的对象(提前暴露对象),使得它所依赖的对象是个完整对象(实例化+初始化),然后再将这个完整对象注入给它。
我们就用下面两个类进行实践,多个类间依赖也是如此。
A 类
packagecn.demo1; importlombok.Getter; importlombok.Setter; @Setter@GetterpublicclassA { privateBb; }
B 类
packagecn.demo1; importlombok.Getter; importlombok.Setter; @Setter@GetterpublicclassB { privateAa; }
配置文件 test1.xml
<?xml version="1.0" encoding="UTF-8"?> <beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <beanid="a"class="cn.demo1.A"> <propertyname="b"ref="b"/> </bean> <beanid="b"class="cn.demo1.B"> <propertyname="a"ref="a"/> </bean> </beans>
DefaultSingletonBeanRegistry 类中的几个特别重要的属性
// 一级缓存 存放完整Bean对象(实例化+初始化)privatefinalMap<String, Object> singletonObjects = newConcurrentHashMap<>(256); // 三级缓存 存放一个lambda表达式privatefinalMap<String, ObjectFactory<?>> singletonFactories = newHashMap<>(16); // 二级缓存 存放一个半成品bean对象(只是实例化还未初始化),提前暴露privatefinalMap<String, Object> earlySingletonObjects = newConcurrentHashMap<>(16);
循环依赖问题应该是出现属性填充的时候
doCreateBean 这个方法
可以参照 createBeanInstance 查看 Spring 是怎么实例化的
protectedObjectdoCreateBean(StringbeanName, RootBeanDefinitionmbd, @NullableObject[] args) throwsBeanCreationException { // bean的包装类BeanWrapperinstanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 就只是bean的实例化instanceWrapper = createBeanInstance(beanName, mbd, args); } Objectbean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 一般为truebooleanearlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName)); // ....省略部分if (earlySingletonExposure) { // 这里是将一段lambda放入三级缓存中,可以看见bean填充属性之前会将三级缓存创建好,它传入了一个还未初始化的beanaddSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } ObjectexposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } // ..........省略部分returnexposedObject; }
addSingletonFactory
// 其中singletonFactory是一个lambda表达式protectedvoidaddSingletonFactory(StringbeanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { // 如果我们一级缓存中不存在这个叫beanName的beanif (!this.singletonObjects.containsKey(beanName)) { // 放入三级缓存中this.singletonFactories.put(beanName, singletonFactory); // 把二级缓存中叫beanName的半成品bean删除this.earlySingletonObjects.remove(beanName); // 标记当前注册的beanthis.registeredSingletons.add(beanName); } } }
lambda 所执行的方法
protectedObjectgetEarlyBeanReference(StringbeanName, RootBeanDefinitionmbd, Objectbean) { ObjectexposedObject = bean; // 普通bean是进不来的if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (SmartInstantiationAwareBeanPostProcessorbp : getBeanPostProcessorCache().smartInstantiationAware) { exposedObject = bp.getEarlyBeanReference(exposedObject, beanName); } } // 直接返回传进来的bean,返回的是一个还未初始化的bean,是提前暴露的returnexposedObject; }
populateBean 中有调用了 applyPropertyValues 这个方法具体详情请点击这里 applyProertyValues
protectedvoidapplyPropertyValues(StringbeanName, BeanDefinitionmbd, BeanWrapperbw, PropertyValuespvs) { // Create a deep copy, resolving any references for values.List<PropertyValue> deepCopy = newArrayList<>(original.size()); booleanresolveNecessary = false; for (PropertyValuepv : original) { if (pv.isConverted()) { deepCopy.add(pv); } else { // 属性名字StringpropertyName = pv.getName(); //当你引用另一个bean的时候,会把它封装成RuntimeBeanReference这个对象,便于操作ObjectoriginalValue = pv.getValue(); // 这里是解析的工作,也就是会产生循环依赖产生的地方ObjectresolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); // 省略.... } }
applyPropertyValues 中有个重要的方法调用,省略无关代码
// 我们当前需要要的就是publicObjectresolveValueIfNecessary(ObjectargName, @NullableObjectvalue) { // 当前bean的属性值的类型正是这个if (valueinstanceofRuntimeBeanReference) { RuntimeBeanReferenceref = (RuntimeBeanReference) value; returnresolveReference(argName, ref); } // 省略... }
resolveReferance 中有一段代码
// 这个方法会调用getBean@NullableprivateObjectresolveReference(ObjectargName, RuntimeBeanReferenceref) { // 省略...// 上面一般进不去,直接看这个重点resolvedName = String.valueOf(doEvaluate(ref.getBeanName())); // 获取所依赖的beanbean = this.beanFactory.getBean(resolvedName); // 省略... }
getBean 从而到这个 doGetBean 方法,其他代码不多说,最主要是下面这个
其中有一段代码,首先它会尝试从缓存中获取到 bean,如果获取不到就创建这个 bean
ObjectsharedInstance = getSingleton(beanName);
获取缓存 bean 的顺序是,先从一级缓存中取,若不存在,从二级缓存中取,若还是不存在,则从三级缓存中取
@NullableprotectedObjectgetSingleton(StringbeanName, booleanallowEarlyReference) { // 一级缓存中是否存在ObjectsingletonObject = this.singletonObjects.get(beanName); // 如果想要获取的bean正在创建中且无一级缓存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) { // 调用三级缓存,这个地方就会调用我们的lambda表达式了/** *() -> getEarlyBeanReference(beanName, mbd, bean) *这里就是我们解决办法的地方,因为所有普通的bean会首先提前进行三级缓存 *所以这里会获取到还未初始化的bean,从而赋值到所依赖当前singletonObject对象的bean */singletonObject = singletonFactory.getObject(); // 放入二级缓存中this.earlySingletonObjects.put(beanName, singletonObject); // 三级缓存中移除当前beanName的lambda表达式this.singletonFactories.remove(beanName); } } } } } } // 完整对象或者还未初始化的对象returnsingletonObject; }
最后经历这个就获取到一个半成品对象所依赖的一个完整对象,然后再将完整对象注入半成品对象中。
该历程仅代表当前这个项目工程