spring循环依赖

循环依赖可以是自己依赖自己,两对象相互依赖,多个对象之间的间接依赖三种情况。

循环依赖主要场景:单例setter注入、多例setter注入、构造器循环依赖、生产代理对象产生的循环依赖、使用@DependsOn产生的循环依赖。

  • spring解决单例的setter注入

       通过spring的三级缓存:

// 一级缓存,用于保存实例化、注入和初始化完成的bean实例。该缓存中的bean可以直接使用 
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
// 二级缓存,用于保存实例化完成的bean实例(尚未填充属性),用于解决循环依赖
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
// 三级缓存,用于保存bean工厂对象,用于解决循环依赖
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);

 

获取bean的主要方法:

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 首先从一次缓存中取
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果一级缓存中没取到, 并且对象正在创建中
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            // 然后从二级缓存中取
            singletonObject = this.earlySingletonObjects.get(beanName);
            // 如果二级缓存没取到, 且允许singletonFactories通过getObject()获取
            if (singletonObject == null && allowEarlyReference) {
                Map var4 = this.singletonObjects;
                synchronized(this.singletonObjects) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            // 最后从三级缓存中取
                            ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                // 提前曝光bean实例(raw bean),用于解决循环依赖 
                                singletonObject = singletonFactory.getObject();
                                // 如果获取到就放入二级缓存, 并且从三级缓存中移除
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }

        return singletonObject;
    }

A和B相互依赖:

从一级缓存中获取A实例,如果获取不到,A首先完成初始化的第一步,并提前暴露到singletonFactories中。

接着进行A初始化第二步,发现自己依赖B,尝试去get(B),发现B还没有创建。

于是B开始初始化,进行初始化第二步时发现自己依赖A,于是尝试get(A)、尝试一级缓存获取、尝试从二级缓存获取都没有,尝试从三级缓存获取A对象,拿到了还没有初始化完全的A。

B拿到A后顺利完成初始化阶段2、3,最终A也完成了初始化。

 

  • 多例循环依赖问题可以通过把bean改成单例
  • 构造器循环依赖通过使用@Lazy注解
  • 生成代理对象产生的循环依赖可以使用@Lazy注解,延迟加载或是使用@DependsOn注解,指定加载先后关系或是修改文件名称,改变循环依赖类的加载顺序
  • 使用@DependsOn产生的循环依赖找到@DependsOn注解循环依赖的地方,迫使它不循环依赖
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiha_zhu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值