Spring5源码解析9-doGetBean概述

接上回,AbstractApplicationContext#refresh调用AbstractApplicationContext#finishBeanFactoryInitialization来初始化所有的非懒加载单例 Bean。在该AbstractApplicationContext#finishBeanFactoryInitialization方法内部通过调用AbstractBeanFactory#doGetBean来获取 Spring 容器所管理的 Bean。

AbstractBeanFactory#doGetBean

AbstractBeanFactory#doGetBean源码如下:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                          @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    // 如果这个 name 是 FactoryBean 的beanName (&+beanName),就删除& , 返回beanName ,传入的name也可以是别名,也需要做转换
    // 注意 beanName 和 name 变量的区别,beanName是经过处理的,经过处理的beanName就直接对应singletonObjects中的key
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    // 根据beanName尝试从singletonObjects获取Bean
    // 获取不到则再尝试从earlySingletonObjects,singletonFactories 从获取Bean
    // 这段代码和解决循环依赖有关
    Object sharedInstance = getSingleton(beanName);
    // 第一次进入sharedInstance肯定为null
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            } else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 如果sharedInstance不为null,也就是非第一次进入
        // 为什么要调用 getObjectForBeanInstance 方法,判断当前Bean是不是FactoryBean,如果是,那么要不要调用getObject方法
        // 因为传入的name变量如果是(&+beanName),那么beanName变量就是(beanName),也就是说,程序在这里要返回FactoryBean
        // 如果传入的name变量(beanName),那么beanName变量也是(beanName),但是,之前获取的sharedInstance可能是FactoryBean,需要通过sharedInstance来获取对应的Bean
        // 如果传入的name变量(beanName),那么beanName变量也是(beanName),获取的sharedInstance就是对应的Bean的话,就直接返回Bean
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // 判断是否循环依赖
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        // 获取父BeanFactory,一般情况下,父BeanFactory为null,如果存在父BeanFactory,就先去父级容器去查找
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            } else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            } else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            } else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        // 创建的Bean是否需要进行类型验证,一般情况下都不需要
        if (!typeCheckOnly) {
            // 标记 bean 已经被创建
            markBeanAsCreated(beanName);
        }

        try {
            // 获取其父类Bean定义,子类合并父类公共属性
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            // 获取当前Bean依赖的Bean的名称 ,@DependsOn
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 如果当前Bean依赖其他Bean,把被依赖Bean注册给当前Bean
                    registerDependentBean(dep, beanName);
                    try {
                        // 先去创建所依赖的Bean
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            if (mbd.isSingleton()) {
                // 创建单例Bean
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        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.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            } else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                // 创建prototype Bean,每次都会创建一个新的对象
                Object prototypeInstance = null;
                try {
                    // 回调beforePrototypeCreation方法,注册当前创建的原型对象
                    beforePrototypeCreation(beanName);
                    // 创建对象
                    prototypeInstance = createBean(beanName, mbd, args);
                } finally {
                    // 回调 afterPrototypeCreation 方法,告诉容器该Bean的原型对象不再创建
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            } else {
                // 如果既不是单例Bean,也不是prototype,则获取其Scope
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    // 创建对象
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        } finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                } catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                    "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        } catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    // 对创建的Bean进行类型检查
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        } catch (TypeMismatchException ex) {
            if (logger.isTraceEnabled()) {
                logger.trace("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

主要流程都已经在上述的源码中增加了注释,读者可以自己查阅。其中,我觉得最主要是要明白以下几点:

Object sharedInstance = getSingleton(beanName);

Object sharedInstance = getSingleton(beanName);这段代码是解决循环依赖的关键,先大概看一下,留个印象,具体的等后面有空讲一下循环依赖吧。

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

//getSingleton(beanName, true);源码
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //singletonObjects 就是Spring内部用来存放单例Bean的对象池,key为beanName,value为Bean
    Object singletonObject = this.singletonObjects.get(beanName);
    // singletonsCurrentlyInCreation 存放了当前正在创建的bean的BeanName
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // earlySingletonObjects 是早期单例Bean的缓存池,此时Bean已经被创建(newInstance),但是还没有完成初始化
            // key为beanName,value为Bean
            singletonObject = this.earlySingletonObjects.get(beanName);
            //是否允许早期依赖
            if (singletonObject == null && allowEarlyReference) {
                //singletonFactories 单例工厂的缓存,key为beanName,value 为ObjectFactory
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //获取早期Bean
                    singletonObject = singletonFactory.getObject();
                    //将早期Bean放到earlySingletonObjects中
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

transformedBeanName 和 getObjectForBeanInstance 的作用

调用doGetBean方法时会传入name变量,表明需要从容器中获取那个 Bean。transformedBeanName除了在处理别名之外,这里会有以下几种情况:

第一种情况,直接往容器中注册 Bean。

@Bean
public UserBean userBean() {
    return new UserBean("shen", 111);
}

在这种情况下,name变量如果为userBean,那么就是要从容器中获取UserBean对象。

调用transformedBeanName方法返回beanName对象的取值userBean

然后根据beanName去容器中获取相应的Bean,而获取到的就是UserBean对象。

最后调用getObjectForBeanInstance方法,返回的还是UserBean对象。

第二种情况,通过FactoryBean往容器中注册 Bean

@Bean
public FactoryBean userBean() {
    return new FactoryBean<UserBean>() {
        @Override
        public UserBean getObject() throws Exception {
            return new UserBean("shen", 111);
        }

        @Override
        public Class<?> getObjectType() {
            return UserBean.class;
        }
    };
}

这里又可以分为两种情况:

第一种情况:

如果name变量如果为userBean,那么也要从容器中获取UserBean对象。

调用transformedBeanName方法返回beanName对象的取值为userBean

然后根据beanName去容器中获取相应的Bean,而获取到的是FactoryBean对象。

最后调用getObjectForBeanInstance方法,发现是从容器中获取UserBean对象,于是调用FactoryBean#getObject返回UserBean对象。

第二种情况:

name变量如果为&userBean,那么就是要从容器中获取FactoryBean对象本身。

调用transformedBeanName方法返回beanName对象的取值为userBean

然后根据beanName去容器中获取相应的Bean,而获取到的是FactoryBean对象,

最后调用getObjectForBeanInstance方法,就是要获取FactoryBean对象,于是方法返回FactoryBean对象。

@DependsOn

通过源码可以知道,Spring 在创建 Bean 之前,首先会创建当前 Bean 所有依赖的 Bean。

String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dep : dependsOn) {
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        // 如果当前Bean依赖其他Bean,把被依赖Bean注册给当前Bean
        registerDependentBean(dep, beanName);
        try {
            // 先去创建所依赖的Bean
            getBean(dep);
        } catch (NoSuchBeanDefinitionException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
        }
    }
}

那什么是当前 Bean 所有依赖的 Bean 呢?也就是说,String[] dependsOn = mbd.getDependsOn();什么情况下这个数组中会有值呢?

在 Spring 中有这个一个注解:@DependsOn。这个注解一般用的很少(碰巧最近项目中用到了这个注解,哈哈哈)。来看一下 Spring 文档中是怎么描述的:

Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialization.
A depends-on declaration can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency. Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, a depends-on declaration can also control shutdown order.

机器翻译:当前 bean 所依赖的 bean。任何指定的 bean 都保证在此 bean 之前由容器创建。当一个 bean 不是通过属性或构造函数参数显式依赖于另一个 bean,而是依赖于另一个 bean 初始化的副作用时,很少使用。依赖项声明既可以指定初始化时间依赖项,也可以指定(在只有单例 bean 的情况下)对应的销毁时间依赖项。在销毁给定 bean 之前,首先销毁定义与给定 bean 的依赖关系的依赖 bean。因此,依赖声明也可以控制关机顺序。

举个例子

@Service
public class OrderService {

    public OrderService() {
        System.out.println("OrderService create");
    }


    @PreDestroy
    public void destroy() {
        System.out.println("OrderService destroy");
    }
}
@DependsOn("orderService")
@Service
public class UserService {

    public UserService() {
        System.out.println("UserService create");
    }


    @PreDestroy
    public void destroy() {
        System.out.println("UserService destroy");
    }
}
@Configuration
@ComponentScan
public class DependsOnMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(DependsOnMain.class);
        context.close();
    }
}
//运行结果
OrderService create
UserService create
UserService destroy
OrderService destroy

createBean(beanName, mbd, args);

在 Spring 中存在者多种 scope,Spring 会根据不用的 scope 选用不同的初始化方式。但是,不管怎么样,Spring 在底层创建 Bean 的时候都是通过调用AbstractAutowireCapableBeanFactory#createBean方法来创建对象的。

那 Spring 究竟是怎么创建 Bean 的呢?AbstractAutowireCapableBeanFactory#createBean方法内部到底做了什么事情呢?循环依赖该怎么解决呢?

未完待续...


源码注释 GITHUB 地址:https://github.com/shenjianeng/spring-code-study

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容