Spring依赖循环
Spring依赖循环
DefaultSingletonBeanRegistry源码
源码注释:
public class DefaultSingletonBeanRegistry
extends SimpleAliasRegistry implements SingletonBeanRegistry {
// 已经创建的单实例 bean 的 beanName 和 instance 的映射关系集
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 正在创建的的单实例 bean 的 beanName 和 ObjectFactory instance 的映射关系集
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 正在创建的单实例 bean 的 beanName 和 instance 的映射关系集, 用于解决循环依赖
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 已经成功创建的单实例 bean 的 beanName 集合
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
// 正在创建的单实例 bean 的 beanBean 集合
private final Set<String> singletonsCurrentlyInCreation
= Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 在检测某个 bean 是否正在创建时需要排除的在检测外的 bean 的 beanName 集合
private final Set<String> inCreationCheckExclusions
= Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 这个记录方法调用链出现的异常
@Nullable
private Set<Exception> suppressedExceptions;
//表示当前所有的单例是否正在被销毁
private boolean singletonsCurrentlyInDestruction = false;
// 已经销毁的单实例 bean 的 beanName 和 instance 的映射关系集
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
/**
* 外部bean与被包含在外部bean的所有内部bean集合包含关系的缓存
* Map between containing bean names: bean name to Set of bean names that the
* bean contains.
*/
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
/**
* dependentBeanMap存放的是 依赖当前bean的 所有的bean的集合
* Map between dependent bean names: bean name to Set of dependent bean names.
*/
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
// bean 实例化时需要依赖的 bean 的 beanName 集合映射关系集
private final Map<String, Set<String>> dependenciesForBeanMap
= new ConcurrentHashMap<>(64);
// SingletonBeanRegistry接口的registerSingleton方法的实现
@Override
public void registerSingleton(String beanName, Object singletonObject)
throws IllegalStateException {
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
synchronized (this.singletonObjects) {
// 是否已经创建, 如果有创建抛出异常
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" +
singletonObject + "] under bean name '"
+ beanName + "': there is already object [" + oldObject + "] bound");
}
addSingleton(beanName, singletonObject);
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 加入到已创建集合
this.singletonObjects.put(beanName, singletonObject);
// 从正在创建的缓存集合中移除
this.singletonFactories.remove(beanName);
// 从正在创建的集合中移除
this.earlySingletonObjects.remove(beanName);
// beanName 添加到已注册的 beanName 集合中
this.registeredSingletons.add(beanName);
}
}
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);
}
}
}
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
// allowEarlyReference: 当 singletonObjects 和 earlySingletonObjects 都没有取到时,
// 是否到 singletonFactories 缓存中去取
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存获取,key=beanName value=bean
Object singletonObject = this.singletonObjects.get(beanName);
// singletonObject为空,且该bean正在创建中(假设不在创建中那么肯定是还没被实例化以及提前曝光的,继续查找没有意义)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从二级缓存获取,key=beanName value=bean
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果 earlySingletonObjects 没有取到,并且允许循环引用, 就去singletonFactories取BeanFactory
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//通过getObject()方法获取bean,获取到的实例不单单是提前曝光出来的实例,
//它还经过了SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法处理过。
//这也正是三级缓存存在的意义,用户可以通过重写该后置处理器对提前曝光的实例进行一些操作
singletonObject = singletonFactory.getObject();
// 将三级缓存生产的bean放入二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// 删除三级缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
// 返回一个单实例 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);
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 + "'");
}
// 主要判断 bean 是否正在创建, 如果正在创建, 抛出异常
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 从 ObjectFactory 的 getObject 获取实例
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;
}
// 创建单实例 bean 失败处理
afterSingletonCreation(beanName);
}
// 如果是一个新的单实例 bean, 添加单实例 bean
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
// 记录发生的异常栈
protected void onSuppressedException(Exception ex) {
synchronized (this.singletonObjects) {
if (this.suppressedExceptions != null) {
this.suppressedExceptions.add(ex);
}
}
}
// 移除指定的单实例 bean
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
// 是否包含指定的 bean
@Override
public boolean containsSingleton(String beanName) {
return this.singletonObjects.containsKey(beanName);
}
// 返回所有的单实例名称
@Override
public String[] getSingletonNames() {
synchronized (this.singletonObjects) {
return StringUtils.toStringArray(this.registeredSingletons);
}
}
// 获取单实例的数量
@Override
public int getSingletonCount() {
synchronized (this.singletonObjects) {
return this.registeredSingletons.size();
}
}
// 指定 bean 是否在检测是否正在创建时是否需要排除
public void setCurrentlyInCreation(String beanName, boolean inCreation) {
Assert.notNull(beanName, "Bean name must not be null");
if (!inCreation) {
this.inCreationCheckExclusions.add(beanName);
} else {
this.inCreationCheckExclusions.remove(beanName);
}
}
// 判断指定的 bean 是否正在创建
public boolean isCurrentlyInCreation(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return (!this.inCreationCheckExclusions.contains(beanName) &&
isActuallyInCreation(beanName));
}
protected boolean isActuallyInCreation(String beanName) {
return isSingletonCurrentlyInCreation(beanName);
}
// 判断单实例 bean 是否正在创建
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
// 创建单实例 bean 的前置处理, 主要判断 bean 是否正在创建
// 如果没有创建, 从正在创建的集合中移除, 如果正在创建, 抛出异常
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) &&
!this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
// 创建单实例 bean 的前置处理, 从正在创建的集合中移除
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName)
&& !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName +
"' isn't currently in creation");
}
}
// 将 bean 添加到需要销毁的集合中
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
}
/**
* Register a containment relationship between two beans, e.g. between an inner
* bean and its containing outer bean.
* <p>
* Also registers the containing bean as dependent on the contained bean in
* terms of destruction order.
*
* @param containedBeanName the name of the contained (inner) bean
* @param containingBeanName the name of the containing (outer) bean
* @see #registerDependentBean
*/
// ??? 暂时没看懂这个 containedBeanMap 的作用
public void registerContainedBean(String containedBeanName,
String containingBeanName) {
synchronized (this.containedBeanMap) {
Set<String> containedBeans
= this.containedBeanMap.computeIfAbsent(containingBeanName,
k -> new LinkedHashSet<>(8));
if (!containedBeans.add(containedBeanName)) {
return;
}
}
registerDependentBean(containedBeanName, containingBeanName);
}
// 为指定的 bean 添加一个依赖的 bean
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans = this.dependentBeanMap.computeIfAbsent(canonicalName,
k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName,
k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
// 判断一个 bean 是否依赖另一个 bean
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
private boolean isDependent(String beanName, String dependentBeanName,
@Nullable Set<String> alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
// 判断一个 bean 是否有依赖
protected boolean hasDependentBean(String beanName) {
return this.dependentBeanMap.containsKey(beanName);
}
// 获取一个 bean 的所有依赖的 bean 的 beanName 集合
public String[] getDependentBeans(String beanName) {
Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
if (dependentBeans == null) {
return new String[0];
}
synchronized (this.dependentBeanMap) {
return StringUtils.toStringArray(dependentBeans);
}
}
// 返回创建这个 bean 时所依赖的的 bean 的 beanName 集合
public String[] getDependenciesForBean(String beanName) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(beanName);
if (dependenciesForBean == null) {
return new String[0];
}
synchronized (this.dependenciesForBeanMap) {
return StringUtils.toStringArray(dependenciesForBean);
}
}
// 销毁所有的单实例
public void destroySingletons() {
if (logger.isTraceEnabled()) {
logger.trace("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
// 销毁依赖的 bean
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
clearSingletonCache();
}
// 清除所有缓存
protected void clearSingletonCache() {
synchronized (this.singletonObjects) {
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;
}
}
// 销毁指定的 bean
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
removeSingleton(beanName);
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
// 销毁依赖的 bean
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// 先销毁依赖的 bean
Set<String> dependencies;
synchronized (this.dependentBeanMap) {
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isTraceEnabled()) {
logger.trace("Retrieved dependent beans for bean '" +
beanName + "': " + dependencies);
}
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName);
}
}
// Actually destroy the bean now...
if (bean != null) {
try {
bean.destroy();
} catch (Throwable ex) {
if (logger.isInfoEnabled()) {
logger.info("Destroy method on bean with name '" +
beanName + "' threw an exception", ex);
}
}
}
// Trigger destruction of contained beans...
Set<String> containedBeans;
synchronized (this.containedBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
destroySingleton(containedBeanName);
}
}
// Remove destroyed bean from other beans' dependencies.
synchronized (this.dependentBeanMap) {
for (Iterator<Map.Entry<String, Set<String>>> it
= this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Set<String>> entry = it.next();
Set<String> dependenciesToClean = entry.getValue();
dependenciesToClean.remove(beanName);
if (dependenciesToClean.isEmpty()) {
it.remove();
}
}
}
// 清除缓存
this.dependenciesForBeanMap.remove(beanName);
}
// 返回已创建的实例的缓存
public final Object getSingletonMutex() {
return this.singletonObjects;
}
}
具体原理说明
三级缓存
上述源码中,主要是下面的3个对象核心,实现3级缓存
/** 一级缓存:用于存放完全初始化好的 bean **/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** 二级缓存:存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** 三级级缓存:存放 bean 工厂对象,用于解决循环依赖 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/**
bean 的获取过程:先从一级获取,失败再从二级、三级里面获取
创建中状态:是指对象已经 new 出来了但是所有的属性均为 null 等待被 init
*/
这里我将缓存分为三级:
singletonObject
:一级缓存,该缓存key = beanName, value = bean;
这里的bean是已经创建完成的,该bean经历过实例化->属性填充->初始化以及各类的后置处理。因此,一旦需要获取bean时,我们第一时间就会寻找一级缓存earlySingletonObjects
:二级缓存,该缓存key = beanName, value = bean;
这里跟一级缓存的区别在于,该缓存所获取到的bean是提前曝光出来的,是还没创建完成的。也就是说获取到的bean只能确保已经进行了实例化,但是属性填充跟初始化还没有做完(AOP情况后续分析),因此该bean还没创建完成,仅仅能作为指针提前曝光,被其他bean所引用singletonFactories
:三级缓存,该缓存key = beanName, value = beanFactory;
在bean
实例化完之后,属性填充以及初始化之前,如果允许提前曝光,spring
会将实例化后的bean
提前曝光,也就是把该bean
转换成beanFactory
并加入到三级缓存。在需要引用提前曝光对象时再通过singletonFactory.getObject()
获取。registeredSingletons
:保存着所有注册过单例的beanName
,是一个set
确保不重复
检测循环依赖的过程如下:
-
A 创建过程中需要 B,于是 A 将自己放到三级缓里面 ,去实例化 B
-
B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了!
-
- 然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 A
- B 顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)
-
然后回来接着创建 A,此时 B 已经创建结束,直接从一级缓存里面拿到 B ,然后完成创建,并将自己放到一级缓存里面
-
如此一来便解决了循环依赖的问题
根据beanName获取对应的对象
/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
手工简化版依赖循环
/**
* 放置创建好的bean Map
*/
private static Map < String, Object > cacheMap = new HashMap < > (2);
public static void main(String[] args) {
// 假装扫描出来的对象
Class[] classes = { A.class, B.class };
// 假装项目初始化实例化所有bean
for (Class aClass: classes) {
getBean(aClass);
}
// check
System.out.println(getBean(B.class).getA() == getBean(A.class));
System.out.println(getBean(A.class).getB() == getBean(B.class));
}
@SneakyThrows
private static < T > T getBean(Class < T > beanClass) {
// 本文用类名小写 简单代替bean的命名规则
String beanName = beanClass.getSimpleName().toLowerCase();
// 如果已经是一个bean,则直接返回
if (cacheMap.containsKey(beanName)) {
return (T) cacheMap.get(beanName);
}
// 将对象本身实例化
Object object = beanClass.getDeclaredConstructor().newInstance();
// 放入缓存
cacheMap.put(beanName, object);
// 把所有字段当成需要注入的bean,创建并注入到当前bean中
Field[] fields = object.getClass().getDeclaredFields();
for (Field field: fields) {
field.setAccessible(true);
// 获取需要注入字段的class
Class < ? > fieldClass = field.getType();
String fieldBeanName = fieldClass.getSimpleName().toLowerCase();
// 如果需要注入的bean,已经在缓存Map中,那么把缓存Map中的值注入到该field即可
// 如果缓存没有 继续创建
field.set(object, cacheMap.containsKey(fieldBeanName) ?
cacheMap.get(fieldBeanName) : getBean(fieldClass));
}
// 属性填充完成,返回
return (T) object;
}
为什么要三级缓存,而不是二级
Spring通过提前曝光
,直接曝光到二级缓存
已经可以解决循环依赖问题了,为什么一定要三级缓存
?
如果循环依赖的时候,所有类又都需要Spring AOP自动代理
,那Spring
如何提前曝光?曝光的是原始bean
还是代理后的bean
?
使用三级缓存而非二级缓存并不是因为只有三级缓存才能解决循环引用问题,其实二级缓存同样也能很好解决循环引用问题。使用三级而非二级缓存并非出于IOC
的考虑,而是出于AOP
的考虑,即若使用二级缓存,在AOP
情形下,注入到其他bean
的,不是最终的代理对象,而是原始对象。
并不是说使用二级缓存就无法将aop
的代理对象注入问题,本质应该说是初始spring
是没有解决循环引用问题的,设计原则是 bean
实例化、属性设置、初始化之后 再 生成aop
对象,但是为了解决循环依赖但又尽量不打破这个设计原则的情况下,使用了存储了函数式接口的第三级缓存; 如果使用二级缓存的话,可以将aop
的代理工作提前到 提前暴露实例的阶段执行; 也就是说所有的bean
在创建过程中就先生成代理对象再初始化和其他工作; 但是这样的话,就和spring
的aop
的设计原则相驳,aop
的实现需要与bean
的正常生命周期的创建分离; 这样只有使用第三级缓存封装一个函数式接口对象到缓存中, 发生循环依赖时,触发代理类的生成。
Spring为什么不使用二级缓存?Spring 动态代理时是如何解决循环依赖的?为什么要使用三级缓存?
总结
Spring虽然解决了Bean对象的循环依赖,但是是有条件限制的
- 对象必须为单例模式,
Spring
的容器只缓存作用域为singleton
的对象 - 必须为属性注入循环依赖,如果为构造函数则不行
为什么要3层,不要2层,主要就是第三层的Bean对象工厂,这个Bean对象工厂用于创建返回这个Bean对象的单例,需要判断该对象是否有AOP,如果有AOP,那么返回Bean对象的代理对象,没有AOP,返回Bean对象本身。
参考
第三章 spring-bean之DefaultSingletonBeanRegistry(3)
Spring源码分析3-DefaultSingletonBeanRegistry