美文网首页
Spring源码分析---单例的加载获取

Spring源码分析---单例的加载获取

作者: shoulda | 来源:发表于2018-07-05 21:43 被阅读0次

    前面一篇文章中讲解了从缓存中加载bean,如果缓存中不存在已经加载的单例bean,就需要实现bean的加载过程。

        public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
            Assert.notNull(beanName, "'beanName' must not be null");
            Map var3 = this.singletonObjects;
            synchronized(this.singletonObjects) {
            //首先检查对应的bean是否已经加载过,因为singleton模式其实就是复用已创建的bean,所以这一步是必须的。
                Object singletonObject = this.singletonObjects.get(beanName);
              //如果为空才可以进行singleton的bean的初始化
                if (singletonObject == null) {
                    if (this.singletonsCurrentlyInDestruction) {
                        throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while the 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 {
                        //初始化bean
                        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 != NULL_OBJECT ? singletonObject : null;
            }
        }
    

    上述代码中使用了回调方法,使得程序可以在单例创建的前后做一些准备以及处理操作,而真正的获取单例bean的方法其实并不是再次方法中实现的,他的实现逻辑是在ObjectFactory类型的实例singletonFactory中实现的。

    (1)检查缓存是否已经加载过

    (2)若没有加载,则记录beanName的正在加载状态

    (3)加载单例前记录加载状态

    beforeSingletonCreation()方法记录加载状态,通过this.singletonsCurrentlyInCreation.add(beanName)将当前正要创建的bean记录在缓存中,这样便可以对循环依赖进行检测。

     protected void beforeSingletonCreation(String beanName) {
            if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
        }
    

    (4)通过调用参数传入的ObjectFactory的个体Object方法实例化bean.

    (5)加载单例后的处理方法调用

    同步骤(3)的记录加载状态相似,当bean加载结束后需要移除缓存中对bean的正在加载状态的记录。

     protected void afterSingletonCreation(String beanName) {
            if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
                throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
            }
        }
    

    (6)将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态

     protected void addSingleton(String beanName, Object singletonObject) {
            Map var3 = this.singletonObjects;
            synchronized(this.singletonObjects) {
                this.singletonObjects.put(beanName, singletonObject != null ? singletonObject : NULL_OBJECT);
                this.singletonFactories.remove(beanName);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    

    (7)返回结果

    虽然我们已经从外部加载了bean的逻辑架构,但现在我们还没有开始对bean加载功能的探索,之前提到过,bean的加载逻辑其实是在传入的ObjectFactory类型的参数singletonFactory中定义的。

    参考:《spring源码深度解析》

    相关文章

      网友评论

          本文标题:Spring源码分析---单例的加载获取

          本文链接:https://www.haomeiwen.com/subject/nlhmuftx.html