《系列二》-- 8、单例bean的创建

阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。

写在开始前的话:

阅读spring 源码实在是一件庞大的工作,不说全部内容,单就最基本核心部分包含的东西就需要很长时间去消化了:

  • beans
  • core
  • context

实际上我在博客里贴出来的还只是一部分内容,更多的内容,我放在了个人,fork自 spring 官方源码仓了; 而且对源码的学习,必须是要跟着实际代码层层递进的,不然只是干巴巴的文字味同嚼蜡。

https://gitee.com/bokerr/spring-framework-5.0.x-study

这个仓设置的公共仓,可以直接拉取。



Spring源码阅读系列--全局目录.md



1 源码入口概述

不管是何种作用域的bean 创建,最终都会指向: “如何从零开始创建bean”,而这个话题前文已经讲解过了。

本文重点介绍,单例作用域的bean 在这个过程中的动作有何异同。

img2222222.png

这里显然是定义了一个回调操作:

sharedInstance 声明的类型是 Object

Object sharedInstance;

看 sharedInstance 的定义,重点看它的第二个参数,经典匿名内部类写法。这里 createBean() 接收 了bean 相关配置信息;

当在 getSingleton(beanName, ObjectFactory) 方法内部调用 ObjectFactory 的 getObject() 方法时,这些参数将会真正登场。

sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    public Object getObject() throws BeansException {
        try {
            // 准备完成后回调  由子类 AbstractAutowireCapableBeanFactory 实现方法
            return createBean(beanName, mbd, args);
        } catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
            // Also remove any beans that received a temporary reference to the bean.
            // 出错,单例工厂销毁该 bean
            destroySingleton(beanName);
            throw ex;
        }
    }
});

接下来我们先看看 getSingleton(beanName, ObjectFactory) 干了什么:

2 getSingleton(beanName, ObjectFactory) 的行为

口头挨个介绍过于干巴巴了,下边直接贴出加了注释的代码:


/**
 * Return the (raw) singleton object registered under the given name,
 * creating and registering a new one if none registered yet.
 *
 * @param beanName         the name of the bean
 * @param singletonFactory the ObjectFactory to lazily create the singleton
 *                         with, if necessary
 * @return the registered singleton object
 */
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) { // 新创建bean,单例对象池中不存在,否则直接方法返回
            if (this.singletonsCurrentlyInDestruction) { // bean 已经被废弃,不能再加载它,抛异常退出
                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 + "'");
            }
            // 进行bean重复创建的校验,如果当前bean已经在创建流程中抛异常,众所周知单例bean必须唯一
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                // 校验通过后,调用 ObjectFactory 的 getObject() 进一步回调 createBean() 方法
                singletonObject = singletonFactory.getObject();
                // 有没有觉得这也太简单了?其实不然,bean 加载的重头戏还在后边: createBean() 
                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;
                }
                // bean 首次加载后再次校验,它是否是真的第一次被加载
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                // 如果是一个新的单例bean,那么把它假如缓存中,从这里进去看到的一定会是:三级缓存
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

总结

针对单例作用域bean 的创建,这里会根据缓存进行判断,需要保证全局唯一。

  1. getSingleton() 返回 sharedInstance时,实际上最终得到的是回调: createBean()的返回结果

  2. sharedInstance 就只可能有两种类型: 普通bean 或者 FactoryBean

然后进入如下逻辑,根据 sharedInstance 提取实际的bean

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

posted @ 2023-06-24 10:05  bokerr  阅读(45)  评论(0编辑  收藏  举报