美文网首页
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