spring源码解析 -- 构造bean

Spring源码解析 -- 读取bean元数据
spring源码解析 -- 构造bean
spring源码解析 -- 注入属性
spring源码解析 -- Spring Context
Spring源码解析 -- AOP原理(1)
Spring源码解析 -- AOP原理(2)
Spring源码解析 -- SpringMvc原理

源码分析基于spring 4.3.x

前面文章已经分析了spring如何加载xml配置中的bean元数据,现在来分析一下spring构造bean的过程。
关于阅读源码的思路,可参考 -- 如何阅读java源码

BeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("application.xml"));
Blog bean = (Blog)xmlBeanFactory.getBean("blog");

XmlBeanFactory的父类AbstractBeanFactory是spring中一个很重要的类,他为BeanFactory提供基础服务。构造bean就是由该类实现的。
AbstractBeanFactory#doGetBean

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

    final String beanName = transformedBeanName(name);
    Object bean;

    Object sharedInstance = getSingleton(beanName); // #1
    if (sharedInstance != null && args == null) {
        ...
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  // #2
    }

    else {
        if (isPrototypeCurrentlyInCreation(beanName)) { // #3
            throw new BeanCurrentlyInCreationException(beanName);
        }

        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {   // #4
            ...
        }

        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);    // #5
        }

        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  // #6
            checkMergedBeanDefinition(mbd, beanName, args);

            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 + "'");
                    }
                    registerDependentBean(dep, beanName);   
                    try {
                        getBean(dep);   // #7
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {     // #8
                    try {
                        return createBean(beanName, mbd, args); // #9
                    }
                    catch (BeansException ex) {
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            ... 
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {   // #10
        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;
}

#1 单例的bean,先从缓冲中查询
getSingleton方法会查询
singletonObject,earlySingletonObjects,singletonFactories等缓存,它们都是简单的map,缓存了单例的bean,正在创建的bean和ObjectFactory对象。

#2 如果构造的bean是FactoryBean,进行对应的处理
getObjectForBeanInstance方法会根据参数beanInstance进行处理,如果beanInstance是FactoryBean,会调用其getObject()方法创建bean,如果不是,返回直接返回该beanInstance参数。
FactoryBean是spring提供的一个扩展接口,用户实现该接口可以自定义bean的创建。

#3 如果现在正在创建这个bean,则直接报错,这时很可能陷入循环引用了
#4 当前BeanFactory不存在对应的BeanDefinition,尝试通过父BeanFactory构造bean
#5 标记这个bean正在构造中
#6 获取BeanDefinition
前面解析spring加载bean数据的文章中说过,spring会将bean元数据转化为BeanDefinition,存入DefaultListableBeanFactory#beanDefinitionMap属性中。
getMergedLocalBeanDefinition方法会获取对应BeanDefinition,如果BeanDefinition存在ParentName,会获取父BeanDefinition,再合并元数据。

#7 先构造依赖的bean
#8 使用ObjectFactory构造并注册一个bean,getSingleton方法也要完成构造bean的准备和善后工作。
#9 匿名的ObjectFactory,调用AbstractAutowireCapableBeanFactory#createBean进行实际的构造bean工作
#10 bean类型转换

spring中bean有singleton,prototype等范围,这里只关注singleton类型的bean的构造过程。

#8步骤,DefaultSingletonBeanRegistry#getSingleton(注意getSingleton有重载方法)

    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) {
                ...
                beforeSingletonCreation(beanName);  // #1
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    singletonObject = singletonFactory.getObject(); // #2
                    newSingleton = true;
                }
                ...
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);    // #3
                }
            }
            return singletonObject;
        }
    }

#1 仅做错误检查,也是提供给子类的扩展方法
#2 真正构造bean的方法,调用AbstractBeanFactory#doGetBean方法#9步骤的匿名类处理,实际调用AbstractAutowireCapableBeanFactory#createBean
#3 单例的bean,加入缓冲中

真正的构造bean方法
AbstractAutowireCapableBeanFactory#createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    if (logger.isTraceEnabled()) {
        logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);   // #1
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    try {
        mbdToUse.prepareMethodOverrides();  // #2
    }
    ...

    try {
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);   // #3
        if (bean != null) {
            return bean;
        }
    }
    ...

    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);   // #4
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    ...
}

#1 确保jdk已加载bean的class
#2 对bean的lookup-method和replace-method做检查工作
#3 spring的扩展机制,调用BeanPostProcessor#postProcessBeforeInstantiation方法,
注意,如果resolveBeforeInstantiation返回非null对象,这里将直接返回该对象作为bean,spring不再构造该bean。
#4 继续构造bean

AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {

    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);   // #1
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);  // #2
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);   // #3
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    ...

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);   // #4
        exposedObject = initializeBean(beanName, exposedObject, mbd);   // #5
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    ...

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);     // #6
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

#1 查询BeanWrapper缓冲
#2 构造一个空的(属性未注入)bean,生成BeanWrapper
#3 spring扩展机制,调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
#4 populateBean负责注入属性到bean中,后面有对应文章解析该步骤
#5 spring扩展机制,调用Aware方法和init方法,并调用BeanPostProcessor#postProcessAfterInitialization方法。
#6 如果bean存在Destroy方法,或存在对应的DestructionAwareBeanPostProcessor,注册该bean为disposable。(该bean销毁时要调用对应的销毁机制)

这里涉及到循环引用的处理,比较繁琐,所以省略了很多代码,只保留bean创建相关的代码。

BeanWrapper是对bean的包装类,提供了对bean的class,property进行操作的方法。

#2步骤,AbstractAutowireCapableBeanFactory#createBeanInstance

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        Class<?> beanClass = resolveBeanClass(mbd, beanName);   // #1

        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }

        if (mbd.getFactoryMethodName() != null)  {  // #2
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {   // #3
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) { 
            if (autowireNecessary) {
                return autowireConstructor(beanName, mbd, null, null);  // #4
            }
            else {
                return instantiateBean(beanName, mbd);  // #5
            }
        }

        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  // #6
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
        return instantiateBean(beanName, mbd);
    }


#1 获取bean的class
#2 如果存在factoryMethod,通过factoryMethod构造bean
#3 判断该class已经构造过bean了
#4 使用之前选择好的构造函数构造bean
#5 使用无参构造函数构造bean
#6 spring根据构造函数的参数,自行选择构造函数,逻辑较复杂。

下面看看使用无参构造方法构造bean,AbstractAutowireCapableBeanFactory#instantiateBean -> SimpleInstantiationStrategy#instantiate

public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
        if (bd.getMethodOverrides().isEmpty()) {
            Constructor<?> constructorToUse;
            synchronized (bd.constructorArgumentLock) {
                constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse == null) {
                    final Class<?> clazz = bd.getBeanClass();
                    if (clazz.isInterface()) {
                        throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {
                        if (System.getSecurityManager() != null) {
                            ...
                        }
                        else {
                            constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);   // #1
                        }
                        bd.resolvedConstructorOrFactoryMethod = constructorToUse;   // #2
                    }
                    catch (Throwable ex) {
                        throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                    }
                }
            }
            return BeanUtils.instantiateClass(constructorToUse);    // #3
        }
        else {
            return instantiateWithMethodInjection(bd, beanName, owner);     // #4
        }
    }

#1 获取无参构造函数
#2 添加无参构造函数加入到BeanDefinition缓存中
#2 BeanUtils#instantiateClass通过构造函数构造bean
#3 bean中存在lookup-method或replace-method,必须使用CGLIB构造bean

到这里,bean已经构造完成,下一步就是注入属性了。

如果您觉得本文不错,欢迎关注我的微信公众号,您的关注是我坚持的动力!


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