Spring源码学习-容器BeanFactory Bean的创建-探寻Bean的新生之路

Posted zzlevolflash

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码学习-容器BeanFactory Bean的创建-探寻Bean的新生之路相关的知识,希望对你有一定的参考价值。

写在前面

上面四篇文章讲了Spring是如何将配置文件一步一步转化为BeanDefinition的整个流程,下面就到了正式创建Bean对象实例的环节了,我们一起继续学习吧。

2.初始化Bean对象实例

Resource resource = new ClassPathResource("beanFactory.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Student student = beanFactory.getBean(Student.class);

仍然使用我们最开的一串代码来讲解,前四章我们说了那么多其实只是创建了BeanFactory这个容器,并将BeanDefinition对象解析完毕,而真正的对象创建则是在BeanFactory.getBean()中执行的。


2.1 起源,探寻Bean的新生之路

一切起源于BeanFactory.getBean(),而对getBean()的实现是在AbstractBeanFactory这个类中实现的,所以我们着眼此类进行源码的阅读。如下为AbstractBeanFactory的继承实现图

技术图片

技术图片

getBean()方法调用了本类中自定义的doGetBean方法,接下来进入doGetBean()方法观察。

protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
        //1、解析beanName,找出bean真正的名称
        final String beanName = transformedBeanName(name);
        Object bean;

        //2.尝试从单例缓存池中直接获取对象
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            //3.该容器缓存中没有,开始尝试加载父容器,检查父容器中是否存在该Bean对象
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }
            //4.父容器中仍然不存在,获取解析好的BeanDefinition,开始准备自己创建Bean
            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//获取bean的根路径信息
                checkMergedBeanDefinition(mbd, beanName, args);
                //重要一步,检查依赖关系,提前创建依赖的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 + "'");
                        }
                        registerDependentBean(dep, beanName);
                        getBean(dep);
                    }
                }
                //5.检查BeanDefinition的scope属性,并执行不同的创建方法,总体大同小异,着重关注单例的创建方法即可。
                if (mbd.isSingleton()) {
                    //6、极为重要的一点,通过getSingleton(String beanName,ObjectFactory objectFactory)创建对象,并且实例化getObject()方法
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    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, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                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;
            }
        }
        if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
            try {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

上面的代码很长,乍一看真的会让初学者头皮发麻,但是没关系,我们将它拆解开来一步一步分析。

  1. transformedBeanName(String):提取对应Bean的名称。定义在SimpleAliasRegistry中,用于获取bean的真实名称。
  2. DefaultSingletonBeanRegistry.getSingleton(Stirng,Boolean):尝试从缓存中直接获取bean或者通过ObjectFactory中获取。关于此方法的详解,请点击。
  3. getObjectForBeanInstance():根据Bean取出我们真正需要的对象(判断指定的bean是否是一个FactoryBean,如果是FactoryBean会判断需求的是本身还是factory的创建对象。)
  4. isPrototypeCurrentlyInCreation(beanName):判断是否进入了循环依赖的无限循环
  5. registerDependentBean(dep, beanName):此段代码主要是找出当前Bean的所有依赖对象,并且循环对这些依赖进行注册和创建。
  6. getSingleton(String,ObjectFactory):针对不同的scope进行各自的初始化操作。
  7. 做最后的类型转换(还不太懂)

至此,一个bean的完整创建流程就走完了。具体的细节,我们接下来一个一个慢慢的看。


2.2 明辨,找出我们真正的目标

首先,我们进入第一段代码

技术图片

在transformedBeanName(beanName)中,传入的参数并非真正的beanName,这里的参数可能是别名,也可能是factoryBean的名称,所以要进行一系列的解析,主要的解析分为两步:

  1. 尝试解析是否是FactoryBean名称,(关于FactoryBean如果不理解,可以访问:Spring之FactoryBean 代码如下:
    //解析是否是FactoryBean:BeanFactoryUtils.transformedBeanName(String name)
    public static String transformedBeanName(String name) {
        Assert.notNull(name, "'name' must not be null");
        String beanName = name;
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        return beanName;
    }
    代码很简单,就是判断beanName是否是以“&”开头,然后进行截取。
  1. 尝试判断该名称是否是某个bean的别名。
    //判断别名:SimpleAliasRegistry.canonicalName(String name)
    public String canonicalName(String name) {
        String canonicalName = name;
        String resolvedName;
        do {
      //从别名集合中循环查找,直到最底层真正的bean名称
            resolvedName = this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        }
        while (resolvedName != null);
        return canonicalName;
    }
依然很简单,尝试从实现定义好的别名集合中进行查询,寻找真正的bean。

2.3 尝试从缓存中直接获取对象

接下来是doGetBean中的第三个方法,getSingleton(String beanName, boolean allowEarlyReference)

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //1.尝试从单例缓存中直接获取对象
    Object singletonObject = this.singletonObjects.get(beanName);
    //2.如果单例缓存中无法获取对象,且该对象在正在创建对象标记池里。
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            //3.从提前创建对象池中获取该对象
            singletonObject = this.earlySingletonObjects.get(beanName);
            //4.对象仍然为空且允许循环依赖
            if (singletonObject == null && allowEarlyReference) {
                //5.尝试从ObjectFactory池中获取对象的ObjectFactory,并创建该对象。
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

public boolean isSingletonCurrentlyInCreation(String beanName) {
    return this.singletonsCurrentlyInCreation.contains(beanName);
}

此方法代码其实不难理解,主要的难点是几个概念上的问题。首先观察该方法中用到的该类的几个参数。

  1. 单例对象缓存池
    /** Cache of singleton objects: bean name --> bean instance */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
    如注解,这是Spring的单例对象池,所有的单例对象创建完毕后都会以beanName ->singletonObject 的形式放入该Map集合中
  2. 对象预创建标记池
    /** Names of beans that are currently in creation */ private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
    这是Spring为了解决循环依赖的一个标记集合,具体概念留在后面介绍
  3. 预创建单例对象缓存池
    /** Cache of early singleton objects: bean name --> bean instance */ private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
    此集合是保存预创建单例对象的集合
  4. 预创建单例对象缓存池
    /** Cache of singleton factories: bean name --> ObjectFactory */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
    此集合是保存ObjectFactory的集合,至于何时、何种情况Spring会创建ObjectFactory。且ObjectFactory、BeanFacotry、FactoryBean他们的关系,也在下面会做说明。

小tip:ObjectFactory、BeanFactory、FactoryBean之间的关系和联系

  • BeanFactory:这是我们大家非常熟悉的接口,Spirng管理Bean容器最原始接口,我们此次研究的入口getBean()就是在此接口中定义。
  • FactoryBean:在上文2.2中我们已经讨论了FactoryBean的情况,作为一个Bean的工厂对象,它也可以作为一个bean对象直接获取,关于BeanFactory和FactoryBean的详细信息,可查看该文章:BeanFactory和FactoryBean
  • ObjectFactory:与FactoryBean很相似的是ObjectFactory也是用于创建一个对象的,且它存在的意义主要用于解决循环依赖。例如A、B两个对象,A中有B属性,B中有A属性。那么在创建A时发现需要注入B,这时创建B,在创建B时发现又需要注入A,这就形成了循环依赖。而Spring正是利用ObjectFactory解决了这个问题,其原理就是在创建A时就将一个A的ObjectFactory对象放入了缓存中,那么在B注入A时就用这个ObjectFactory创建的对象注入B中,这样就解决了循环依赖的问题。具体的代码在下面会详细介绍。

2.4根据Bean实例,获取真正需要的对象

getObjectForBeanInstance()是一个非常重要的方法,Spring在获取了每个Bean的对象之后,都要调用该方法完成最后的步骤以取得我们真正想要的Bean。说到很多人肯定会疑惑,什么是“真正需要”,点进该方法,我们就知道了。

protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

    if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
        throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
    }

    //判断实例不是FactoryBean类型或该实例名称以获取FactoryBean开头 ,满足任何一个条件直接返回实例
    //即满足两个条件无非有两个条件1.该对象不是FactoryBean,判断短路直接返回。2.该对象是FactoryBean,且用户想直接获取FactoryBean
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        //通过上述,至此可以完全确定该对象是Factory对象,下方就是通过对象的factory-method创建对象的过程。
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

上述重要就是一个短路判断,如果该对象不是一个FactoryBean或者用户试图直接获取FactoryBean对象,则该对象就已经是我们想要的对象,直接返回即可,否则的话就意味着我们需要通过FactoryBean内部定义好的factory-method来创建我们需要的Bean对象。而我们追入getObjectFromFactoryBean()中,查看如下代码:

//FactoryBeanRegistrySupport.getObjectFromFactoryBean(...)
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        if (factory.isSingleton() && containsSingleton(beanName)) {
            synchronized (getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        if (object != null && shouldPostProcess) {
                            try {
                //执行后处理器
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                        }
                        this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
                    }
                }
                return (object != NULL_OBJECT ? object : null);
            }
        }
        else {
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (object != null && shouldPostProcess) {
                try {
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }

而遗憾的是我们还是没有看到真正创建对象的方法,但通过前面的阅读,我们已经可以发现Spring在一个方法的真正核心处理部分处,都会以doXXXX开头,而其余都是对这个核心处理的一层层包装与协助。

4.1代码如莲花开放般的优美:处理器BeanPostProcess

在观察核心代码之前,我们先观察后面一个重要的方法。postProcessObjectFromFactoryBean(),在spring的整个架构中给予了用户各种拓展和自定义的权利,这也是Spring被广泛称赞:代码优美的原因之一。而这里的执行后处理器操作就是很重要的一环,进入该方法的子类AbstractAutowireCapableBeanFactory观察Spirng是如何让代码变得如此优美的。

    //AbstractAutowireCapableBeanFactory.java
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
            return applyBeanPostProcessorsAfterInitialization(object, beanName);
    }

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {

            Object result = existingBean;
            for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
                result = beanProcessor.postProcessAfterInitialization(result, beanName);
                if (result == null) {
                    return result;
                }
            }
            return result;
    }
//BeanPostProcessor.java
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

观察代码,可以知道Spring循环了Bean所注册的所有BeanPostProcess,并在这里依次调用了其postProcessAfterInitialization()方法,而该方法的实现交由用户来自己实现。于是乎,通过解析我们就能知道:在Spring中:如果想让一个Bean在初始化完成后做一些特殊处理,实现BeanPost.postProcessAfterInitialization()即可。最后有一个小提醒:我们一定要清晰的认识到,此时我们是在修饰一个FactoryBean创建的Bean对象,而并非正常流程创建的Bean对象哦,例如我们一直讨论的这个FactoryBean,它本身作为一个Bean对象是在什么时候执行了PostPorcess方法了呢?后续我们拭目以待吧

4.2柳暗花明,终于获取最终需要的对象

了解完处理器之后,让我们点入doGetObjectFromFactoryBean(),发现里面的代码就非常简单明了。

//FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(...)
    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
            throws BeanCreationException {
        Object object;
        try {
            //安全校验相关的,先无视掉吧。
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                                //调用Factory的getObject方法
                                return factory.getObject();
                            }
                        }, acc);
                }catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }else {
            //调用Factory的getObject方法
                object = factory.getObject();
            }
        }catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }
        if (object == null && isSingletonCurrentlyInCreation(beanName)){
            throw new BeanCurrentlyInCreationException(
                    beanName, "FactoryBean which is currently in creation returned null from getObject");
        }
        return object;
    }

一层一层终于我们到了最里边,在这里我们发现最终对象正是由当初获取的FactoryBean对象的getObject()方法完成。如果读到这里已经有些绕不过来,想不起自己从何处而来的话,往上翻一翻,看清楚自己一路走来之路哦。下面我们就重新回到起源之路上,继续往下探索。但由于真正的Bean的创建流程很长,所以这篇文章先写到这里,下面单开一篇文章来写Bean对象的实例化。

以上是关于Spring源码学习-容器BeanFactory Bean的创建-探寻Bean的新生之路的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码学习-容器BeanFactory BeanDefinition的创建-解析资源文件

Spring源码学习之BeanFactory体系结构

Spring 源码学习~12容器的拓展功能简介

Spring 源码学习~12容器的拓展功能简介

不一样的视角来学习Spring源码之容器与Bean---上

Spring源码解析 - BeanFactory接口体系解读