获取单例

前言

上一篇文章缓存中获取单例bean讲述了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例bean,就需要重新开始加载bean的所有过程了,这篇文章讲述的就是从头开始加载bean的过程中的一个步骤---获取单例。

获取单例

Spring中使用getSingleton的重载方法实现bean的加载过程,在getBean方法源码中体现:

      sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });

 来看一下getSingleton方法的源码:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        //全局变量需要同步
        synchronized (this.singletonObjects) {
            //首先检查对应的bean是否被加载过,因为singleton模式其实就是复用以前创建的bean,所以这一步是必须的
            Object singletonObject = this.singletonObjects.get(beanName);
            //如果为空才可以进行singleton的bean初始化
            if (singletonObject == null) {
                //当工厂的单例对象处于销毁状态时,不允许创建单例bean
                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 (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                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 ex) {
                    // Has the singleton object implicitly appeared in the meantime ->
                    // if yes, proceed with it since the exception indicates that state.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    //加入缓存
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

 上述代码其实是使用了回调方法,使得程序在单例创建的前后做一些准备及处理操作,而真正的获得单例bean的方法其实并不是在此方法中实现的,其实逻辑是在ObjectFactory类的实例singletonFactory中实现的。上述代码的处理操作包括如下几步:

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

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

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

  其中beforeSingletonCreation(beanName),为空实现,里面没有任何逻辑,其实不是,这个方法中做了一个重要的操作:记录加载状态,也就是通过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) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }

(7)返回处理结果。

上述代码的处理过程就到这里结束了。

总结:虽然我们已经从外部了解了加载bean的逻辑架构,但我们现在还没有开始对bean加载功能的探索,之前的文章提到过,bean的加载逻辑其实是在传入的ObjectFactory类的参数singletonFactory中定义的,我们反推参数的获取,得到如下代码:

sharedInstance = getSingleton(beanName, new ObjectFactory<Object>{
    public Object getObject() thows BeansWxception{
                        try {
                            return createBean(beanName, mbd, args);
                        }
        }
catch (BeansException ex) { destroySingleton(beanName); throw ex; } });

ObjectFactory的核心部分其实只是调用了createBean方法,所以接下来我们还需要到createBean中去追寻bean的加载过程。

参考:《Spring源码深度解析》 郝佳 编著:

posted on 2018-12-20 10:52  AoTuDeMan  阅读(427)  评论(0编辑  收藏  举报

导航