Spring循环依赖源码解析

本文详细剖析了Spring中处理循环依赖的过程,包括Bean的生命周期、三级缓存机制以及AOP代理的创建。通过实例展示了从单例池获取Bean、处理循环依赖、早期间代理引用以及初始化后AOP的处理步骤,揭示了Spring如何优雅地解决循环依赖问题。
摘要由CSDN通过智能技术生成

Spring循环依赖源码解析

个人记录,有误指出

什么是循环依赖?

比如:A对象依赖了B对象,B对象又依赖了A对象

class A {
    @Autowired
    private B b;
}

class B {
    @Autowired
    private A a;
}
以Bean生命周期的形式描述循环依赖过程:

1、在singletonsCurrentlyInCreation中存储A,表示A正在创建,

2、A实例化得到A的原始对象,将原始对象生成代理对象的lambda表达式放到第三级缓存<aName, A原始对象>

3、进行依赖注入,此时A依赖了B,

4、填充B属性(进行getBean()),从单例池中找对应bName对应的Bean,找不到并且发现A正在创建中(在一个if表达式上面:isSingletonCurrentlyInCreation),代表A出现了循环依赖,然后去第二级缓存中找,找不到,并且allowEarlyReference默认为true,然后去第三级缓存中找,找到的是一个lambda表达式,然后执行lambda表达式(wrapIfNecessary()方法就是执行AOP的方法,会判断你是否有切面),对A进行AOP,得到A代理对象,然后将A代理对象保存到第二级缓存当中,

5、填充其他属性

6、A初始化——>(判断是否提前进行AOP)——>AOP——>代理对象

循环依赖用到的集合

1、singletonsCurrentlyInCreation记录是否正在创建的Bean

2、earlyProxyReferences记录是否Bean提前进行过AOP

3、一级缓存为:singletonObjects

4、二级缓存为:earlySingletonObjects

5、三级缓存为:singletonFactories

doGetBean()

A Bean在创建的时候,会使用lambda表达式,把createBean()方法作为形参传到getSingleton()方法中

// 根据Scope去创建bean
// Create bean instance.
if (mbd.isSingleton()) {
    // 获取单例bean,如果获取不到则创建一个bean,并且放入单例池中
    sharedInstance = getSingleton(beanName, () -> {
        try {
            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;
        }
    });
    // sharedInstance可能是一个FactoryBean,所以需要单独再去factoryBeanObjectCache中去获取对应的对象
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
getSingleton()

在getSingleton()方法中,会调用beforeSingletonCreation()方法对该创建的Bean存到一个Set集合当中,该singletonsCurrentlyInCreation集合存放的就是正在创建的A Bean的beanName,在getSingleton方法中后面的finally代码块中会将该singletonsCurrentlyInCreation集合中存放打beanName进行remove移出。

该getSingleton()方法主要的作用是执行lambda表达式,将创建的bean添加到单例池,然后返回bean。

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

        // 如果不存在实例,则创建单例bean实例
        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 + "'");
            }
            // 把当前正在创建的beanName添加到singletonsCurrentlyInCreation中,singletonsCurrentlyInCreation是一个Set
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                // singletonFactory是外面传进来的lambda表达式,执行lambda表达式
                // 创建单例bean
                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;
                }
                // 将刚刚正在创建的beanName从singletonsCurrentlyInCreation中移除
                afterSingletonCreation(beanName);
            }

            // 将创建好的单例bean添加到单例池singletonObjects中
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}
doCreateBean()

如果判断当前创建的是单例bean,并且存在于singletonsCurrentlyInCreation的Set集合中,则表示该bean正在创建中,则表示该bean进行了循环依赖,将该Bean的原始对象,封装在lambda表达式中作为value,beanName作为key添加到第三级缓存singletonFactories中。

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 如果当前创建的是单例bean,并且允许循环依赖,并且还在创建过程中,那么则提早暴露
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");
    }
    // 此时的bean还没有完成属性注入,是一个非常简单的对象
    // 构造一个对象工厂添加到singletonFactories中
    // 第四次调用后置处理器
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));  // AService
    //			addEarlySingleton(beanName, bean);
}

向第三级缓存singletonFactories添加的时候,同时将第二级缓存的beanName进行remove移出,实现原子性,二级和三级缓存只能有一个HashMap存放beanName(防止程序出现bug,生成了多个单例bean的代理对象)。

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);  // 已经创建成功的单例列表
			}
		}
	}

在doGetBean()方法中,会在createBean前前去单例池中寻找该Bean,发现单例池中不存在,并且发现该Bean正在创建当中,去二级缓存earlySingletonObjects中寻找,发现为空,去第三级缓存singletonFactories中寻找,执行lambda表达式,返回的代理对象添加到二级缓存中,并且在第三级缓存中删除lambda表达式。

这里防止多个循环依赖同时执行第三级缓存的lambda表达式产生多个代理对象,使用了synchronized锁,所以单例池使用的是ConcurrentHashMap,而第二级和第三级使用的是HashMap,为了提高效率。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);

		// singletonsCurrentlyInCreation存放正在创建的bean
		// isSingletonCurrentlyInCreation为true表示该bean正在创建
		// singletonObject一级缓存单例池根据beanName中找不到bean
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				// 没有earlySingletonObjects会怎么样?
				// 在earlySingletonObjects二级缓存中根据beanName尝试找bean
				singletonObject = this.earlySingletonObjects.get(beanName);

				if (singletonObject == null && allowEarlyReference) {
					// 为什么需要singletonFactories?
					// 尝试在三级缓存中根据beanName寻找bean
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					// bean实例化得到原始对象的时候就会添加到singletonFactories三级缓存中,所以一般不为null
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();  // 执行lambda AOp
						// 因为二级缓存和三级缓存中只能存在一个,为了保证原子性
						// 所以添加进二级缓存后,在三级缓存中删除
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

lambda表示,进行AOP,将进行AOP的bean添加进earlyProxyReferences【是一个ConcurrentHashMap,循环引用时记录是否提前生成了代理对象,key:beanName,value:bean的原始对象】

// bean原始对象
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName); // beanName  aService
    // 判断
    this.earlyProxyReferences.put(cacheKey, bean);

    return wrapIfNecessary(bean, beanName, cacheKey);  //代理对象
}
wrapIfNecessary()

判断是否已经生成代理对象,在实例化前能够实现创建一个代理对象,并且在targetSourcedBeans中存储,所以先判断是否存在于targetSourcedBeans中,如果存在则直接返回代理对象,如果不存在,则根据切面和Bean原始对象创建一个代理对象

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// beanName不为空,并且beanName存在于targetSourcedBeans中,表示这个bean被动态代理了
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 当前这个bean不用被代理
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}

		// 如果是基础bean,或者@Aspect修饰的类不需要被代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		// 获取当前beanClass所匹配的advisors
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

		// 如果匹配的advisors不等于null,那么则进行代理,并返回代理对象
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 基于bean对象和Advisor创建代理对象
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			// 存一个代理对象的类型
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
doCreateBean()部分

在Bean的生命周期到初始化后时,会重新判断是否需要AOP

// Initialize the bean instance.
		// 对象已经暴露出去了
		Object exposedObject = bean;
		try {
			// 3、填充属性 @Autowired
			populateBean(beanName, mbd, instanceWrapper);

			// 4、 初始化 和 BeanPostProcessor
			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) {
			// 在解决循环依赖时,当AService的属性注入完了之后,从getSingleton中得到AService AOP之后的代理对象
			Object earlySingletonReference = getSingleton(beanName, false);  // earlySingletonObjects
			if (earlySingletonReference != null) {
				// 如果提前暴露的对象和经过了完整的生命周期后的对象相等,则把代理对象赋值给exposedObject
				// 最终会添加到singletonObjects中去
				if (exposedObject == bean) { // ②分析二:
					exposedObject = earlySingletonReference;
				}
				// 如果提前暴露的对象和经过了完整的生命周期后的对象不相等
				// allowRawInjectionDespiteWrapping表示在循环依赖时,只能
				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()) {
						// AService的原始对象被注入给了其他bean,但是AService最后被包装了
						// 也就是说其他bean没有用到AService的最终版本
						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 " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}
①分析一:postProcessAfterInitialization()

进入AOP方法,首先会检验是否在生命周期:初始化后之前是否有提前进行过AOP,检查earlyProxyReferences中是否存在该Bean,没有则进行wrapIfNecessary()方法进行创建代理对象,有则返回bean。

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			// earlyProxyReferences中存的是哪些提前进行了AOP的bean,beanName:AOP之前的对象
			// 注意earlyProxyReferences中并没有存AOP之后的代理对象  BeanPostProcessor
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				// 没有提前进行过AOP,则进行AOP
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		// 为什么不返回代理对象呢?
		return bean;   //
	}
②分析二:

在经过初始化生命周期后,检验当前Bean是否和创建的的原始Bean是否相等,相等则赋值第二级缓存存储的代理对象

// 在解决循环依赖时,当AService的属性注入完了之后,从getSingleton中得到AService AOP之后的代理对象
Object earlySingletonReference = getSingleton(beanName, false);  // earlySingletonObjects
if (earlySingletonReference != null) {
    // 如果提前暴露的对象和经过了完整的生命周期后的对象相等,则把代理对象赋值给exposedObject
    // 最终会添加到singletonObjects中去
    if (exposedObject == bean) {
        exposedObject = earlySingletonReference;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值