Spring的循环依赖

场景分析

public  class AService {
    @Autowired
    private BService BService;
    public AService(){
        System.out.println("init aService");
    }
}
public  class BService {
    @Autowired
    private AService aService;
    public BService(){
        System.out.println("init bService");
    }
}

类似于上述代码,在Aservice中依赖BService属性,在BService中依赖Aservice的情况称之为循环依赖。
在spring Bean的生命周期中,当Bean实例化之后,还存在了属性填充,生命周期初始回调,完成aop代理等等阶段。
在初始化AService时,在属性填充节点需要BService对象,但是此时spring容器中不存在BService对象,需要去创建BService。
创建BService的过程中完成了Bean实例化,在属性填充时又需要Aservice对象,但是此时AService还处于属性填充阶段,没有完全初始化好,此时如果Aservice不需要完成aop代理,那么只需要将正在初始化的Aservice对象引用赋给BService中Aservice的属性就好了,当时如果Aservice需要进行aop代理或者其他的一些操作呢?这个问题就是循环依赖的问题。

需要解决循环依赖的问题,就需要了解下spring三级缓存

spring三级缓存

	/** Cache of singleton objects: bean name to bean instance. */
	//单例对象缓存池,经过完整的spring bean的生命周期的单例Bean对象,在spring容器初始化的放入
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	/** Cache of singleton factories: bean name to ObjectFactory. */
	//实例化单例对象的ObjectFactory缓存池,可以获取提前aop之后的对象
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
	/** Cache of early singleton objects: bean name to bean instance. */
	//早期单例对象缓存池,提前aop之后的对象,没有经过完成的spring bean生命周期
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

三级缓存的使用:

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;
}

获取单例对象时,先从一级缓存(singletonObjects)中获取,一级缓存(singletonObjects)获取不到并且获取的bean在当前正在创建的bean集合中时再从三级级缓存(earlySingletonObjects)中获取,三级缓存(earlySingletonObjects)获取不到时,获取二级缓存(singletonFactories)中的ObjectFactory对象并调用ObjectFactory对象的getObject()方法获取提前aop的对象,并放入三级缓存(earlySingletonObjects)中方便下次获取。

spring中循环依赖解决原理

首先需要解决循环依赖,相互依赖的Bean必须是单例的,并且是通过属性注入的。

spring使用了三级缓存来解决循环依赖,当创建一个单例Bean时,spring会将当前创建Bean的名称放入一个集合中,表示该bean处于创建过程中。

//当前正在创建的bean名称集合
private final Set<String> singletonsCurrentlyInCreation =
    Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//当前在创建检查中被排除在外的bean的名称
private final Set<String> inCreationCheckExclusions =
    Collections.newSetFromMap(new ConcurrentHashMap<>(16));
protected void beforeSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}

在实例化bean之后,判断bean是否单例&&是否允许循环依赖&&是否正在创建中,如果是则将生成对应的ObjectFactory对象添加到二级缓存中,该ObjectFactory对象获取获取到提前aop的bean对象。

当有别bean需要此正在创建中的bean时,可以调用ObjectFactory对象的getObject()方法获取提前aop的对象。

这里的“提前aop”可能不太准确,还执行了别的实现了SmartInstantiationAwareBeanPostProcessor接口的Bean后置处理完成除aop以外的事。以下方式是ObjectFactory对象的getObject()方法完成的事:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

关闭循环依赖

AnnotationConfigApplicationContext ann = new AnnotationConfigApplicationContext();
ann.setAllowCircularReferences(false);//关闭循环依赖
ann.register(AppConfig.class);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值