J2EE-029 Spring容器源码解析(四)refresh()三级缓存解析-笔记

当我们相互引用时,如何解决报错和实列化问题

@Service
public class A {
    B b;
    public A(){
        this.b=new B();
    }
}
@Service
public class B {
    A a;
}

这个时候我们注入对象就会出现报错信息,出现了交叉引用,A->B B->A
在这里插入图片描述
那么在Spring中是如何解决的呢?
代码太多们先画图讲解,我们先分清步骤
1.getBean()>从BeanFactory中拿到A Bean对象
2.dogetBean()
>创建Bean对象
3.addSingletonFactory()>创建Bean工厂对象,同时放入3级缓存singletonFactories
4.populateBean()
>依赖注入的对象
4.1.getBean()>从BeanFactory中拿到B Bean对象
4.2.dogetBean()
>创建Bean对象
4.3.addSingletonFactory()==>创建Bean工厂对象,同时放入3级缓存singletonFactories
4.4获得Bean实例,这里面引用A的对象从3级缓存中A的工厂对象创建实例
5.创建完成对象,放入1级缓存singletonObjects在这里插入图片描述
当一级缓存不存在的时候,拿二级缓存,二级缓存不存在则从3级缓存拿,
并将三级缓存的数据剪切达到二级缓存

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

代码分析:

  • 第一次进来判断一级实例是否为空和isSingletonCurrentlyInCreation是否存在,第一次进来肯定为空,我们任何Bean实例都没有
Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {

返回null后,判断为空,根据beanName判断是否是线程安全的,集合中是否有值相等,相等为空

   if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
    }

接下来判断有没有父工厂,我们没有,下一步
标记一下BeanName

   if (!typeCheckOnly) {  //typeCheckOnly==false
       this.markBeanAsCreated(beanName);
 }

this.markBeanAsCreated(beanName);解析
这里有个双端校验锁,主要是防止再加锁的过程中已经有线程进入内部了,所以内部需要再次判断一下。

   protected void markBeanAsCreated(String beanName) {
   //首先有没有包含第一次没有包含
        if (!this.alreadyCreated.contains(beanName)) {
        //加锁
            synchronized(this.mergedBeanDefinitions) {
            //再判断
                if (!this.alreadyCreated.contains(beanName)) {
                //构建Bean
                    this.clearMergedBeanDefinition(beanName);
                    //将Bean添加到构建集合中,BeanName等于已经开始构建了
                    this.alreadyCreated.add(beanName);
                }
            }
        }
    }

拿到tBeanDefinition对象

RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
  if (dependsOn != 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);
                    //多列的没有缓存的效果
                } else if (mbd.isPrototype()) {
                    var11 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }


//为了方便我把需要用的方法copy在一起
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 + "'");
                }
               //检查是否是需要排除的bean如果是则直接抛出异常
                this.beforeSingletonCreation(beanName);
                //是否是新的单列
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {  //默认为True的
                    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;
        }
    }


    protected void beforeSingletonCreation(String beanName) {
    //检查是否是需要排除的bean如果是则直接抛出异常
    //添加到Set集合当中去
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }
// singletonObject = singletonFactory.getObject();这里的Object实质是回调到AbstractBeanFactory只中的方法
   sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                        //创建Bean
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    

this.createBean(beanName, mbd, args);后面层次太深了,这里和方法名一样是创建Bean,最后会走进inject方法,如果有依赖则又会调用一遍getSingleton方法,再一次循环这个过程,最终完成实例的创建

最后后把二级和三级缓存中的数据全部清空,放入一级缓存当中,最后放入注册单例集合

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

那么构造函数的方式可以么?为什么?
不可以
因为解析的时候解析的的方法方法,构造函数不是方法
拿到的为null会报错

MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);

关于为什么使用三级缓存,这里我翻阅了许多博主的文章都说是解决AOP和事务的代理对象的,其实我把代理工厂,Bean工厂都放进二级缓存,用的时候都从二级里面拿不做分层也可以实现啊,为什么必须分三层,我还没搞懂,到时候有答案了再记录吧

最后本来想带领大家一步一步走进去看代码的,但是实在是内部堆栈信息繁琐不知道怎么写出来清晰只能用这样的方式说个代码执行什么流程的大概了。不算博文算笔记吧

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值