spring源码第二篇 循环依赖重点

 循环依赖 老生常谈了 这里大概描述一下场景和把代码重点标注出来

名词介绍

一级缓存(单例池):singletonObjects

二级缓存(存的是工厂方法):singletonFactories

三级缓存:earlySingletonObjects

1 场景介绍

1 A注入B B注入A

A --将A放入二级缓存-A的ioc ----实例化B-将B-放入二级缓存-B-的ioc--将A从二级缓存拿出--执行A的aop--将A从二级缓存放入三级缓存---B实例化完了--放入一级缓存---继续A的ioc--A实例化完了 将A从三级缓存放入一级缓存

2 正常A注入B

A--将A放入二级缓存-A的ioc ----实例化B-将B-放入二级缓存-B-的ioc--B实例化完毕后--将B放入一级缓存---继续A的实例化--A实例化完,将A放入一级缓存

重点

1这2者差距是 三级缓存只有循环依赖的时候 才会将A放入三级缓存 正常就是先放入二级缓存再升级为一级缓存

2 二级缓存放的是工厂方法 只有出现了循环依赖才会调用 提前生成aop对象 目的就是为了B中注入的A是一个proxy代理对象 而不是target被代理对象

3 只有二级升级为三级 或者 一级 , 三级升级为一级 这2种升级 ,二级升级为三级是循环依赖才胡升级 ,三级升级为一级 就是上面的A注入B,B实例化完后 ,A才会升一级,正常都是二级升级为一级

4 spring为啥要三级 本身二级是可以搞定循环依赖 但是循环依赖的时候 没有第二级缓存 就没发提前把依赖对象给Aop 导致注入的是不是一个代理对象

代码具体地方

A--实例化,在doGetBean的第一步先去缓存中拿A

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
@Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject;
    }

 此时A第一次实例化 肯定不在一级缓存和不是当前正在创建 于是这个方法返回null,继续往下走
 

 if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

 于是走到这里 会先走到getsingleton

 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 (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }

                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }

                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject;
        }
    }

 这个方法中开始从一级缓存拿 肯定拿不到 继续走 beforeSingletonCreation会将A置为正在创建中,接下来会走到外面传的lamda表达式也就是开始createBeanA,走到docreateBean里面后有这么一段代码 会将A添加到二级缓存

 boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

这个getEarlyBeanReference是一段lamda表达式(工厂方法) 此时并不会执行,这时候A被置为了创建中和放入了二级缓存,这时候开始对B进行注入 发现B都没注入 开始实例化B,跟A一样会走到这里那么B也会置为了创建中和放入了二级缓存,开始对b进行Ioc,发现要注入A,然后就会去getBean-A 然后就会走到getBean的getSingleton

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
@Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject;
    }

 这时候 A不在一级缓存中 进了if ,条件也满足 于是去三级缓存中拿A这时候 A还在二级缓存呢,于是调用了A的getEarlyBeanReference方法 这时候A假如有Aop 就会提前生成代理,于是A就被放到了三级缓存从二级缓存中挪走了,于是返回给B的A这个field,b于是ioc完了 b这个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 (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }

                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }

                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject;
        }
    }

里面有个

if (newSingleton) {
                    this.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);
            this.registeredSingletons.add(beanName);
        }
    }

 将b从二级缓存中挪出 升级为一级缓存

接下来继续回到A A继续实例化 然后也跟b一样 实例化完了后 从三级缓存挪出 变成一级缓存

总结

1  getBean里的getSinleton只会是循环依赖时候将二级升级为三级,并且执行二级缓存的工厂方法,提前aop,正常从一级缓存直接拿了

2  createBean后的添加缓存是会将有循环依赖的A从三级升级为一级的,正常的B就是二级升级为一级

3 不管是A还是B 在进行ioc之前都会放入二级缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值