文档章节

Spring 源码分析 : 非懒加载的单例 Bean 初始化过程 ( 上 ) ( 2 )

oschina_00
 oschina_00
发布于 2017/04/28 17:20
字数 1128
阅读 20
收藏 0

接着第62行~第78行、第80行~第91行、第93行~第120行有三个判断,显然上面的MultiFunctionBean是一个单例的Bean也是本文探究的重点,因此执行第62行~第78行的逻辑。getSingleton方法不贴了,有一些前置的判断,很简单的逻辑,重点就是调用了ObjectFactory的getObject()方法来获取到单例Bean对象,方法的实现是调用了createBean方法,createBean方法是AbstractBeanFactory的子类AbstractAutowireCapableBeanFactory的一个方法,看一下它的方法实现:

 

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

        throws BeanCreationException {

 

    if (logger.isDebugEnabled()) {

        logger.debug("Creating instance of bean '" + beanName + "'");

    }

    // Make sure bean class is actually resolved at this point.

    resolveBeanClass(mbd, beanName);

 

    // Prepare method overrides.

    try {

        mbd.prepareMethodOverrides();

    }

    catch (BeanDefinitionValidationException ex) {

        throw new BeanDefinitionStoreException(mbd.getResourceDescription(),

                beanName, "Validation of method overrides failed", ex);

    }

 

    try {

        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

        Object bean = resolveBeforeInstantiation(beanName, mbd);

        if (bean != null) {

            return bean;

        }

    }

    catch (Throwable ex) {

        throw new BeanCreationException(mbd.getResourceDescription(), beanName,

                "BeanPostProcessor before instantiation of bean failed", ex);

    }

 

    Object beanInstance = doCreateBean(beanName, mbd, args);

    if (logger.isDebugEnabled()) {

        logger.debug("Finished creating instance of bean '" + beanName + "'");

    }

    return beanInstance;

}

 

前面的代码都没什么意义,代码执行到第31行:

 

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {

    // Instantiate the bean.

    BeanWrapper instanceWrapper = null;

    if (mbd.isSingleton()) {

        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);

    }

    if (instanceWrapper == null) {

        instanceWrapper = createBeanInstance(beanName, mbd, args);

    }

    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);

    Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

 

    // Allow post-processors to modify the merged bean definition.

    synchronized (mbd.postProcessingLock) {

        if (!mbd.postProcessed) {

            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

            mbd.postProcessed = true;

        }

    }

 

    // Eagerly cache singletons to be able to resolve circular references

    // even when triggered by lifecycle interfaces like BeanFactoryAware.

    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&

            isSingletonCurrentlyInCreation(beanName));

    if (earlySingletonExposure) {

        if (logger.isDebugEnabled()) {

            logger.debug("Eagerly caching bean '" + beanName +

                    "' to allow for resolving potential circular references");

        }

        addSingletonFactory(beanName, new ObjectFactory() {

            public Object getObject() throws BeansException {

                return getEarlyBeanReference(beanName, mbd, bean);

            }

        });

    }

 

    // Initialize the bean instance.

    Object exposedObject = bean;

    try {

        populateBean(beanName, mbd, instanceWrapper);

        if (exposedObject != null) {

            exposedObject = initializeBean(beanName, exposedObject, mbd);

        }

    }

    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);

        }

    }

 

    if (earlySingletonExposure) {

        Object earlySingletonReference = getSingleton(beanName, false);

        if (earlySingletonReference != null) {

            if (exposedObject == bean) {

                exposedObject = earlySingletonReference;

            }

            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {

                String[] dependentBeans = getDependentBeans(beanName);

                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);

                for (String dependentBean : dependentBeans) {

                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {

                        actualDependentBeans.add(dependentBean);

                    }

                }

                if (!actualDependentBeans.isEmpty()) {

                    throw new BeanCurrentlyInCreationException(beanName,

                            "Bean with name '" + beanName + "' has been injected into other beans [" +

                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +

                            "] in its raw version as part of a circular reference, but has eventually been " +

                            "wrapped. This means that said other beans do not use the final version of the " +

                            "bean. This is often the result of over-eager type matching - consider using " +

                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");

                }

            }

        }

    }

 

    // Register bean as disposable.

    try {

        registerDisposableBeanIfNecessary(beanName, bean, mbd);

    }

    catch (BeanDefinitionValidationException ex) {

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);

    }

 

    return exposedObject;

}

 

代码跟踪到这里,已经到了主流程,接下来分段分析doCreateBean方法的代码。

 

创建Bean实例

 

第8行的createBeanInstance方法,会创建出Bean的实例,并包装为BeanWrapper,看一下createBeanInstance方法,只贴最后一段比较关键的:

 

// Need to determine the constructor...

Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

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);

 

意思是bean标签使用构造函数注入属性的话,执行第6行,否则执行第10行。MultiFunctionBean使用默认构造函数,使用setter注入属性,因此执行第10行代码:

 

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {

    try {

        Object beanInstance;

        final BeanFactory parent = this;

        if (System.getSecurityManager() != null) {

            beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {

                public Object run() {

                    return getInstantiationStrategy().instantiate(mbd, beanName, parent);

                }

            }, getAccessControlContext());

        }

        else {

            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

        }

        BeanWrapper bw = new BeanWrapperImpl(beanInstance);

        initBeanWrapper(bw);

        return bw;

    }

    catch (Throwable ex) {

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);

    }

}

 

代码执行到13行:

 

public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {

    // Don't override the class with CGLIB if no overrides.

    if (beanDefinition.getMethodOverrides().isEmpty()) {

        Constructor<?> constructorToUse;

        synchronized (beanDefinition.constructorArgumentLock) {

            constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;

            if (constructorToUse == null) {

                final Class clazz = beanDefinition.getBeanClass();

                if (clazz.isInterface()) {

                    throw new BeanInstantiationException(clazz, "Specified class is an interface");

                }

                try {

                    if (System.getSecurityManager() != null) {

                        constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {

                            public Constructor run() throws Exception {

                                return clazz.getDeclaredConstructor((Class[]) null);

                            }

                        });

                    }

                    else {

                        constructorToUse = clazz.getDeclaredConstructor((Class[]) null);

                    }

                    beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;

                }

                catch (Exception ex) {

                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);

                }

            }

        }

        return BeanUtils.instantiateClass(constructorToUse);

    }

    else {

        // Must generate CGLIB subclass.

        return instantiateWithMethodInjection(beanDefinition, beanName, owner);

    }

}

 

整段代码都在做一件事情,就是选择一个使用的构造函数。当然第9行顺带做了一个判断:实例化一个接口将报错。

 

最后调用到30行,看一下代码:

 

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {

    Assert.notNull(ctor, "Constructor must not be null");

    try {

        ReflectionUtils.makeAccessible(ctor);

        return ctor.newInstance(args);

    }

    catch (InstantiationException ex) {

        throw new BeanInstantiationException(ctor.getDeclaringClass(),

                "Is it an abstract class?", ex);

    }

    catch (IllegalAccessException ex) {

        throw new BeanInstantiationException(ctor.getDeclaringClass(),

                "Is the constructor accessible?", ex);

    }

    catch (IllegalArgumentException ex) {

        throw new BeanInstantiationException(ctor.getDeclaringClass(),

                "Illegal arguments for constructor", ex);

    }

    catch (InvocationTargetException ex) {

        throw new BeanInstantiationException(ctor.getDeclaringClass(),

                "Constructor threw exception", ex.getTargetException());

    }

}

 

通过反射生成Bean的实例。看到前面有一步makeAccessible,这意味着即使Bean的构造函数是private、protected的,依然不影响Bean的构造。

 

最后注意一下,这里被实例化出来的Bean并不会直接返回,而是会被包装为BeanWrapper继续在后面使用。

 

来源:五月的仓颉,

www.cnblogs.com/xrq730/p/6361578.html

本文转载自:www.cnblogs.com/xrq730/p/6361578.html

oschina_00
粉丝 5
博文 101
码字总数 0
作品 0
廊坊
私信 提问
Spring Boot Bean生命周期

注:Spring Boot Bean的生命周期,什么是Bean的生命周期,就是Bean从创建到销毁的过程。 Bean的生命周期过程描述 我们先看一下Bean的生命周期过程中都会经历些什么,我先简单解释一下,后面我...

爱编程的帅小伙
2018/07/12
0
0
【死磕 Spring】—– IOC 之分析各 scope 的 bean 创建

原文出自:http://cmsblogs.com 在 Spring 中存在着不同的 scope,默认是 singleton ,还有 prototype、request 等等其他的 scope,他们的初始化步骤是怎样的呢?这个答案在这篇博客中给出。...

chenssy
2018/10/24
0
0
Spring源码解析系列之IOC容器(一)

前言 实际上我所有的博客都是原来对原来印象笔记里笔记内容的加工,关于Spring源码自己已经解析了很多遍,但是时间长总是忘记,写一篇博客权当加强记忆,也算再次学习下大师们的设计思想,思...

后厂村老司机
2018/06/02
0
0
通过循环依赖问题彻底理解SpringIOC的精华

前言 你可能会有如下问题: 1、想看Spring源码,但是不知道应当如何入手去看,对整个Bean的流程没有概念,碰到相关问题也没有头绪如何下手 2、看过几遍源码,没办法彻底理解,没什么感觉,没...

Java填坑之路
2018/11/19
0
0
【Spring】- Bean懒加载机制

Bean类型:singleton/prototype singleton Bean:单例Bean,Bean在使用过程中只实例化1次(默认) prototype Bean:原型Bean, Bean每次使用都实例化新的对象 IOC容器Bean初始化 ①:单例Bean:I...

ZeroneLove
03/02
19
0

没有更多内容

加载失败,请刷新页面

加载更多

对比ubuntu与centos系统 ​​​​

CentOS与Ubuntu该如何选择,哪个更好用。笔者在自媒体平台收集了一些网友的观点,较为经典,分享给大家。至于应该选择哪个,希望看完本文章后,读者心中有数。 观点1:CentOS适用于服务器,U...

老孟的Linux私房菜
今天
12
0
Java的基本类型

一、Java的基本类型 Java的基本类型有哪些? boolean char byte short int long float double ? 延伸思考 思考一:为什么有的书籍说Java存在第9种数据类型? 实际上,JAVA中还存在另外一种基...

yumoop
今天
14
0
OSChina 周四乱弹 —— 富婆小时候

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @猿敲月下码 :#今日歌曲推荐# 分享陈慧娴的单曲《夜机》 《夜机》- 陈慧娴 手机党少年们想听歌,请使劲儿戳(这里) @開源中國張學友 :早上...

小小编辑
今天
23
0
MyMinimad ── Linux下用libmad写的mp3解码播放程序(四)

优化了内存使用,不再使用mmap映射整个文件到内存 /* * 本程序是从 minimad 改进而来,如要更详细的说明请参看 minimad.c * * Gu Zhou, 2009/12/25, SiChuan University, China *...

代码强国
今天
18
0
Minikube安装

1、下载Minikube二进制文件 sudo curl -Lo minikube https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/latest/minikube-linux-amd64 2、设置权限 sudo chmod +x minikube......

RogueQ
今天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部