README

Spring如何解决循环引用的

Bean 循环引用是什么?

在 Spring 容器中,非懒加载的单例对象会在 IOC 容器创建后进行加载,而常说的 Spring 循环引用问题也是在此时发生的。

假设,我想要向 Spring 容器注册两个单例对象 A 与 B,其中 A 对象存在 B 属性,B 对象存在 A 属性(由于单例的特性,该容器只会存在一个该类型的对象),因此会构成循环引用。图示与代码如下:

@Component // 向容器注册一个单例(默认单例)对象 A
class A{
@Autowired // A 对象需要自动注入 B 类型对象
private B b;

}

@Component // 向容器注册一个单例(默认单例)对象 B
class B{
@Autowired // B 对象需要自动注入 A 类型对象
private A a;
}

如何解决循环引用?

Spring如何存储单例对象的?

在了解 Spring 如何解决循环引用之前,我们先了解一下 Spring 是如何存放单例对象的。在 DefaultSingletonBeanRegistry 类中,使用三个 Map 结构的缓存单例对象,这三个 Map 又被称为三级缓存。

一级缓存,用于存储初始化完成的单例对象,也就是我们通常使用的bean。

二级缓存,用于存储实例化后但未初始化的单例对象,此类对象也称被提前暴露的对象。

三级缓存,用于存储能够获取单例对象的对象。

一级缓存

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);三级缓存private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);二级缓存private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

注册标记,已注册的bean对象会被添加到这

private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);

单例对象正在创建标记,正在创建的bean对象会被添加到这,创建完成时会移除

private final Set<String> singletonsCurrentlyInCreation =Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

解决循环引用的思路

首先,我先概述一个 Spring 创建一个 bean 对象的过程(从解决循环引用的角度且不使用 AOP 机制的单例对象),在 Spring 启动之初,单例缓存还不存在任何实例化对象(前提)。

调用 getBean 从单例缓存中获取 bean 对象,存在则返回

通过工厂方法创建一个bean对象

实例化一个对象

添加到三级缓存(切记三级缓存是一个对象工厂,未使用 AOP 的 bean 返回的是原对象,否则返回的是代理对象)

为对象注入依赖属性

通过getBean获取依赖对象实例,一级缓存存储返回一级缓存,将三级缓存存在的对象移动到二级缓存,并返回

初始化使用

将创建的bean添加到一级缓存

下面模拟一下A、B循环引用的解决:

源码分析

接下来,我们将从GetBean方法开始进行源码分析(tips:不需要关注的代码被删减了):

getSingleton-从缓存获取单例对象

从缓存中获取对象的逻辑

// 从多级缓存获取bean,allowEarlyReference==true 则可以从三级缓存获取bean
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 首先通过一级缓存获取bean对象
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 若 Bean 还在创建中,则从二级缓存获取bean对象
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 若二级缓存不存在此bean并且允许提前暴露bean对象则从三级缓存中获取对象工厂 ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 若三级缓存存在,则从三级缓存获取bean对象,然后将生成的bean对象放置到二级缓存中,同时移除三级缓存的对象工厂
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}


// 从一级缓存或传递的工厂中获取bean
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {

synchronized (this.singletonObjects) {
// 从一级缓存获取bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
beforeSingletonCreation(beanName);
boolean newSingleton = false;
try {
// 从对象工厂获取对象bean
singletonObject = singletonFactory.getObject();// createBean
newSingleton = true;
}
if (newSingleton) {
// 将bean对象添加到一级缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}

addSingleton–添加单例对象到缓存

添加对象到缓存中

// 添加bean到一级缓存
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 添加bean到一级缓存
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
// 从三级缓存移除bean
this.singletonFactories.remove(beanName);
// 从二级缓存移除bean
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}


//添加bean到三级缓存
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 确保一级缓存不存在bean后,移除二级缓存,添加三级缓存,添加注册标记
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}

getBean&doGetBean–获取单例对象的逻辑

//--------------------------getBean---------------------------
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
//-------------------------doGetBean--------------------------
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 获取 beanName
final String beanName = transformedBeanName(name);
Object bean;

    // 从单例对象缓存中获取bean(以一级、二级、三级的顺序,若对象出现在三级缓存,将其移动到二级缓存)
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
      // 缓存中获取到该类型实例对象,返回
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
				// 缓存不存在该bean,则创建一个
				if (mbd.isSingleton()) {
          // 如果该bean是单例对象,则通过 getSingleton 获取bean对象(首先从一级缓存获取该bean-此处肯定为空,为空再从工厂获取该bean,同时会将bean对象添加到一级缓存)
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
// 核心点 创建bean的实际调用方法
return createBean(beanName, mbd, args);
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 多例 忽略
}
}
}
// 返回对象
return (T) bean;
}

createBean&doCreateBean–创建单例对象的逻辑

这个是Bean工厂方法的核心,包括了bean的实例化、依赖注入、初始化、销毁回调。

//--------------------------createBean---------------------------
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {

		// 核心代码,创建bean--doCreateBean
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		return beanInstance;
	}
//--------------------------doCreateBean---------------------------
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {

		// 1. 在这里会实例化一个 Bean 对象	
		instanceWrapper = createBeanInstance(beanName, mbd, args);
		
  
  	// 从包装对象中获取bean实例
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
		mbd.resolvedTargetType = beanType;

  	// 允许 MergedBeanDefinitionPostProcessor 修改 bean definition.
		applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

  	// 2. 是否需要提前暴露(条件为 单例&允许循环引用&此单例对象正在创建),需要则暴露对象到三级缓存(ObjectFactory直接返回bean实例)
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
      // 添加 beanfactory 到三级缓存
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
          // 返回原对象或者需要代理对象时返回代理对象
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

  
			Object exposedObject = bean;
      // 2. 为 Bean 对象注入属性
			populateBean(beanName, mbd, instanceWrapper);
			// 3. Bean 对象在这里初始化
			exposedObject = initializeBean(beanName, exposedObject, mbd);
			

      // 循环依赖相关 依次从一级、二级缓存获取 bean(若bean属性注入时出现循环依赖,此bean会出现在二级缓存中)
      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<String>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
              if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                actualDependentBeans.add(dependentBean);
              }
            }
          }
        }
      }

			// 4. 为 Bean 对象添加DisposableBean 回调
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
  
		return exposedObject;
	}

populateBean

有兴趣可看,与循环引用解决关系不是很大

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// bean为空直接返回
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		boolean continueWithPropertyPopulation = true;

    // InstantiationAwareBeanPostProcessors after
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

    // 依赖注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
        // byName自动注入,将依赖的bean放到newPvs中
				autowireByName(beanName, mbd, bw, newPvs);//底层调用GetBean获取对象bean
			}

			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        // byType自动注入,将依赖的bean放到newPvs中
				autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
		}
		// 检查容器是否持有用于处理单态模式Bean关闭时的后置处理器

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			if (hasInstAwareBpps) {
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies(beanName, mbd, filteredPds, pvs);
			}
		}
		// 属性注入,从 pvs 获取属性注入bean中
		applyPropertyValues(beanName, mbd, bw, pvs);
	}

getEarlyBeanReference–从工厂获取早期暴露对象的实现,若出现AOP+循环依赖会返回代理对象

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
        // SmartInstantiationAwareBeanPostProcessor 接口是需要实现aop的类实现的接口
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
        
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
					if (exposedObject == null) {
						return null;
					}
				}
			}
		}
		return exposedObject;
	}

	AbstractAutoProxyCreator
//返回一个代理对象
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
this.earlyProxyReferences.add(cacheKey);
}
return wrapIfNecessary(bean, beanName, cacheKey);
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 已经处理后不再处理
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 不需要增强
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			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;
	}

为什么需要三级缓存二级不可以吗?

我们知道普通对象循环依赖,Spring通过提前暴露非完整对象来实现,只需要两级缓存就能够很好的解决问题。其实,三级缓存主要是为了处理AOP+循环引用的问题,因为常规AOP代理的生成在对象初始化之后,为了处理AOP+循环依赖的问题,Spring将此情况的AOP代理对象生成提前了(不提前找不到代理对象的引用,逻辑就不对了)。

对于AOP+循环依赖,使用三级缓存,通过对象工厂便能够提前获取代理对象;对于普通AOP对象,由于不存在循环依赖,不会被调用工厂方法构造代理对象,也就不会打破生命周期,这是三级缓存存在的意义–延迟普通AOP代理对象的生成。

总结

Spring 通过三级缓存、提前暴露不完整对象实现属性注入期间的循环依赖,因此 Spring 不能解决构造方法循环依赖的问题(彼此无法构造出对象,直接抛出异常)。

AOP+循环依赖情况下,通过打破代理对象原有的生成的时机来实现代理对象的提前暴露,从而解决循环依赖。

参考

https://www.cnblogs.com/youzhibing/p/14337244.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值