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

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

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体系结构,如下图所示:
2019112310099\_1.png
从上图我们看到:  
(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; }

具体的加载流程图如下:
2019112310099\_2.png
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()方法。


来源:http://ddrv.cn/a/88268

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring源码深度解析—bean的加载(上)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏