一看就懂,Spring IOC 三级缓存如何解决循环依赖

历时一周的时间,前后经历4/5次更改,浓缩出本文~

目录

 Bean 创建时机

Spring 创建 bean 三步曲

循环依赖

关键代码


 Bean 创建时机

AbstractApplicationContext.java

public void refresh() { 
        finishBeanFactoryInitialization(beanFactory);  

}

protected finishBeanFactoryInitialization(beanFactory) {

            // Instantiate all remaining (non-lazy-init) singletons.

           beanFactory.preInstantiateSingletons

}    

     

Spring 创建 bean 三步曲

1.  反射调用无参构造创建 bean:   Constructor.newInstance()

2.  为 bean 属性赋值: populateBean()

3.  初始化 bean:initializeBean()

循环依赖

关于循环依赖的问题已经在上图中说明,为了看的更清楚,整理如下流程图:

解释下上图, A依赖B, B依赖A, 

1. spring 获取 a,a 不存在缓存,开始创建

2. a 创建后放入三级缓存

3. 赋值 a 的属性,发现依赖了 b

4. 获取 b, b 不存在缓存,开始创建

5. b 创建后放入三级缓存

6. 赋值 b 的属性, 发现依赖了 a

7. 从三级缓存获取 a (的代理,如果需要的话), 并放入二级缓存(2中操作的)

8. 注入到 b 

9. 初始化 b (生成代理对象)

10. b 放入一级缓存(b 的创建全部完成)

11. 把 b 注入 a

12. 接着 3, 初始化 a,并没有生成代理!

13. 从二级缓存获取 a 的代理对象(7中操作的)

14. 将 a 的代理对象放入一级缓存(b 的创建全部完成)

关键代码

获取 bean

	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object beanInstance;

		// 从缓存中获取,一级->二级->三级, b 初始化时获取 a,从三级缓存获取并移入二级
		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 + "'");
				}
			}
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {

				//缓存中没有,再次尝试从缓存获取,没有则调用 createBean 返回的最终 bean(如果用了aop,是增强的bean) 并放入一级缓存中。
				if (mbd.isSingleton()) {
					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;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {

				}

				else {
				}
					catch (IllegalStateException ex) {
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
			finally {
				beanCreation.end();
			}
		}

		return adaptBeanInstance(name, beanInstance, requiredType);
	}
AbstractBeanFactory.java

创建 bean 并初始化过程:

	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) {
            // 1. 反射创建 bean
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		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");
			}
            // 2. a、b 创建后都会被放入三级缓存:beanName-> singletonFactory
            // b 初始化时,会从三级缓存的 singletonFactory.getObject() 拿到 a 的代理对象
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// 3. 初始化(resolveDependency, 生成代理对象)
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
            // b 在这里会生成代理对象
			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;
	}
AbstractAutowireCapableBeanFactory.java

7 中获取 a 时会从三级缓存中获取,singletonFactory.getObject 时会生成代理:

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
                // 重要!!如果使用了aop, InfrastructureAdvisorAutoProxyCreator 会返回代理对象
				exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
			}
		}
		return exposedObject;
	}

AbstractAutowireCapableBeanFactory.java

总结

1. 一级缓存 存放已经 ready 的 bean,供其他 bean 使用

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

2. 二级缓存,存放循环依赖中首先被创建的 bean(被增强后的单例 bean)

private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

3. 三级缓存, 存放对象名和对象工厂

Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

二级缓存的意义就在于:如果使用了 aop , 缓存了被增强对象,而不是通过三级缓存每次都创建个增强对象。


如果觉得还不错的话,关注、分享、在看(关注不失联~), 原创不易,且看且珍惜~

posted on 2021-08-13 19:22  XuHe1  阅读(282)  评论(0编辑  收藏  举报