SpringIOC的循环依赖解析
Posted lisin-lee-cooper
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringIOC的循环依赖解析相关的知识,希望对你有一定的参考价值。
一.示例代码及解析
循环依赖分为自身依赖于自身、互相循环依赖、多组循环依赖,代码如下所示
@Getter
@Setter
public class ClazzA {
@Autowired
private ClazzB b;
@Autowired
private ClazzA a;
}
@Setter
@Getter
public class ClazzB {
@Autowired
private ClazzA a;
}
public class TestIOCDependence {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
ClazzA clazzA = applicationContext.getBean(ClazzA.class);
System.out.println(clazzA);
System.out.println(clazzA.getB());
}
}
1.创建Bean的方法 doGetBean
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 从缓存中获取Bean 三级缓存
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 这里如果是普通Bean 的话,直接返回,如果是 FactoryBean 的话,返回它创建的那个实例对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Create bean instance.
if (mbd.isSingleton()) {
// 创建单例Bean
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建 bean 实例
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);
}
}
}
// 转化Bean为真正需要的类型,有点像适配器模式
return adaptBeanInstance(name, beanInstance, requiredType);
}
2.核心方法 createBean 中的 doCreateBean
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) {
// 创建 bean 实例,将 bean 实例包装到 BeanWrapper 对象中返回
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 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");
}
// addSingletonFactory 添加 bean 工厂对象到 singletonFactories 缓存中
// 获取原始对象的早期引用,在 getEarlyBeanReference 方法中,会执行 AOP 相关逻辑。若 bean 未被 AOP 拦截 则原样返回 bean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 填充属性 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// 调用 实现的Aware接口和applyBeanPostProcessors 的方法
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);
}
}
return exposedObject;
}
3.getSingleton 三级缓存 ,解决循环依赖
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从 singletonObjects 获取实例,singletonObjects 是成品 bean
Object singletonObject = this.singletonObjects.get(beanName);
// 判断 beanName ,isSingletonCurrentlyInCreation 对应的 bean 是否正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从 earlySingletonObjects 中获取提前曝光未成品的 bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 获取相应的 bean 工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 提前曝光 bean 实例,主要用于解决AOP循环依赖
singletonObject = singletonFactory.getObject();
// 将 singletonObject 放入缓存中,并将 singletonFactory 从缓存中移除
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
二.为什么要使用三级缓存?
1.一级缓存能不能解决问题?
根据Spring创建Bean的流程可知当创建成品A时, 属性赋值需要注入成品B,成品B的创建又需要依赖成品A,此时A未创建,因此会出现死循环。
2.二级缓存能解决问题吗?
在创建A成品时,会在注入属性时提前暴露一个A的半成品,当注入创建B时,会将B依赖的A的半成品赋值给B,此时B成品创建完成时,A成品自然也创建完成。因此二级缓存能解决循环依赖问题。
3.三级缓存的作用是什么?
三级缓存主要是解决 Spring AOP 的特性。AOP 本身就是对方法的增强,并不是所有Bean都会执行AOP,为了统一Spring Bean的创建过程将其放到三级缓存中处理,最终获取到以后调用 getObject 方法返回代理引用或者原始引用。从而解决了 Spring AOP 带来的三级缓存问题。
以上是关于SpringIOC的循环依赖解析的主要内容,如果未能解决你的问题,请参考以下文章