spring源码深度解析---bean的加载(上)

spring源码深度解析—bean的加载(上)

1. 概述

前面我们已经分析了spring对于xml配置文件的解析,接下来我们将对bean的加载进行探索。bean的加载比配置文件的解析要复杂的多。还记得我们在测试读取配置文件后获取bean用的方法吗?context.getBean(“testContructor”),如下所示,这段代码具体实现了什么功能呢?接下来我们将详细分析下。

public class TestDemo {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("construtor.xml");

        TestConstructor test =(TestConstructor) context.getBean("testContructor");

        System.out.println(test.getName());
    }
}

我们看到这个方法是在接口BeanFactory中定义的,我们看下BeanFactory体系结构,如下图所示:
《spring源码深度解析---bean的加载(上)》
从上图我们看到:  
(1)BeanFactory作为一个主接口不继承任何接口,暂且称为一级接口。
(2)有3个子接口继承了它,进行功能上的增强。这3个子接口称为二级接口。
(3)ConfigurableBeanFactory可以被称为三级接口,对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry
(4)ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,无所不包,称为四级接口。(这4级接口是BeanFactory的基本接口体系。继续,下面是继承关系的2个抽象类和2个实现类:)
(5)AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory大部分功能。
(6)AbstractAutowireCapableBeanFactory同样是抽象类,继承自AbstractBeanFactory,并额外实现了二级接口AutowireCapableBeanFactory
(7)DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了最强大的四级接口ConfigurableListableBeanFactory,并实现了一个外来接口BeanDefinitionRegistry,它并非抽象类。
(8)最后是最强大的XmlBeanFactory,继承自DefaultListableBeanFactory,重写了一些功能,使自己更强大。
接下来我们就跟踪getBean方法,首先进入到AbstractBeanFactory.getBean方法中,其内部使用的是doGetBean方法,然后继续跟踪代码

//AbstractBeanFactory中的getBean方法
@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    //提取对应的beanName
    final String beanName = transformedBeanName(name);
    Object bean;
    /*
     *检查缓存中的实例工程是否存在对应的实例
     *为何要优先使用这段代码呢?
     *因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
     *spring创建bean的原则是在不等bean创建完就会将创建bean的objectFactory提前曝光,即将其加入到缓存中,一旦下个bean创建时依赖上个bean则直接使用           *objectFactory
     *直接从缓存中或singletonFactories中获取objectFactory
     */
    // Eagerly check singleton cache for manually registered singletons.
    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);
        }
        //尝试从parentBeanFactory中查找bean
        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 {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }
        //如果不是仅仅做类型检查,则这里需要创建bean,并做记录
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }
        try {
            //将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,同时如果存在父bean的话则合并父bean的相关属性
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            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);
                    try {
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 实例化依赖的bean后对bean本身进行实例化
            if (mbd.isSingleton()) {
                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.
                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, () -> { 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. 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.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; }

具体的加载流程图如下:
《spring源码深度解析---bean的加载(上)》
BeanFactory是Spring IOC容器的鼻祖,是IOC容器的基础接口,所有的容器都是从它这里继承实现而来。可见其地位。BeanFactory提供了最基本的IOC容器的功能,即所有的容器至少需要实现的标准。
BeanFactory体系结构是典型的工厂方法模式,即什么样的工厂生产什么样的产品。BeanFactory是最基本的抽象工厂,而其他的IOC容器只不过是具体的工厂,对应着各自的Bean定义方法。但同时,其他容器也针对具体场景不同,进行了扩充,提供具体的服务。
XmlBeanFactory,只是提供了最基本的IOC容器的功能。而且XMLBeanFactory,继承自DefaultListableBeanFactory。DefaultListableBeanFactory实际包含了基本IOC容器所具有的所有重要功能,是一个完整的IOC容器。

2. FactoryBean

2.1 BeanFactory和FactoryBean区别
BeanFactory和FactoryBean都是接口,那他们有什么区别呢?
(1)BeanFactory以Factory结尾,表明他是一个工厂,用于管理Bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。它为其他具体的IOC容器提供了最基本的规范,例如DefaultListableBeanFactory,
XmlBeanFactory,ApplicationContext 等具体的容器都是实现了BeanFactory,再在其基础之上附加了其他的功能。其源码如下:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    @Nullable
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}

(2)FactoryBean以Bean结尾,表明他是一个bean,不同于普通Bean的是:它是实现了FactoryBean接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。其源码如下:

public interface FactoryBean<T> {
    @Nullable
    T getObject() throws Exception;
    @Nullable
    Class<?> getObjectType();
    default boolean isSingleton() {
        return true;
    }
}

BeanFactory和FactoryBean其实没有什么比较性的,只是两者的名称特别接近,所以有时候会拿出来比较一番,BeanFactory是提供了OC容器最基本的形式,给具体的IOC容器的实现提供了规范,FactoryBean可以说为IOC容器中Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,我们可以在getObject()方法中灵活配置。其实在Spring源码中有很多FactoryBean的实现类,要想深入准确的理解FactoryBean,我们需要分析其源码。
一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。
FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean的形式,如上代码所示。在FactoryBean接口中定义了3个方法:
(1)T getObject():返回由FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中;
(2)boolean isSingleton():返回由FactoryBean创建的Bean实例的作用域是singleton还是prototype;
(3)Class getObjectType():返回FactoryBean创建的Bean类型。
当配置文件中的class属性配置的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。

    原文作者:Spring Cloud
    原文地址: https://blog.csdn.net/uftjtt/article/details/79928970
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞