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