Spring重要接口详解

Spring重要接口详解

BeanFactory继承体系

体系结构图

在这里插入图片描述

ApplicationContext和BeanFactory关系

ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相关的操作其实是委托给这个实例来处理的!之所以选择这个DefaultListableBeanFactory,是因为,他强大。

四级接口继承体系:
  1. BeanFactory 作为一个主接口不继承任何接口,暂且称为一级接口。
  2. AutowireCapableBeanFactory、HierarchicalBeanFactory、ListableBeanFactory 3个子接
    口继承了它,进行功能上的增强。这3个子接口称为二级接口。
  3. ConfigurableBeanFactory 可以被称为三级接口,对二级接口 HierarchicalBeanFactory 进行
    了再次增强,它还继承了另一个外来的接口 SingletonBeanRegistry
  4. ConfigurableListableBeanFactory 是一个更强大的接口,继承了上述的所有接口,无所不
    包,称为四级接口。
BeanFactory 是Spring bean容器的根接口
提供获取bean,是否包含bean,是否单例与原型,获取bean类型,bean 别名的api
AutowireCapableBeanFactory 提供工厂的装配功能。
HierarchicalBeanFactory 提供父容器的访问功能
ConfigurableBeanFactory 如名,提供factory的配置功能,眼花缭乱好多api
ConfigurableListableBeanFactory 集大成者,提供解析,修改bean定义,并初始化单例
ListableBeanFactory 提供容器内bean实例的枚举功能.这边不会考虑父容器内的实例
下面是继承关系的2个抽象类和2个实现类:
  1. AbstractBeanFactory 作为一个抽象类,实现了三级接口 ConfigurableBeanFactory 大部分功
    能。
  2. AbstractAutowireCapableBeanFactory 同样是抽象类,继承自 AbstractBeanFactory ,并额
    外实现了二级接口 AutowireCapableBeanFactory 。
  3. DefaultListableBeanFactory 继承自 AbstractAutowireCapableBeanFactory ,实现了最强
    大的四级接口 ConfigurableListableBeanFactory ,并实现了一个外来接口
    BeanDefinitionRegistry ,它并非抽象类。
  4. 最后是最强大的 XmlBeanFactory ,继承自 DefaultListableBeanFactory ,重写了一些功能,
    使自己更强大。
那为何要定义这么多层次的接口呢?

查阅这些接口的源码和说明发现,每个接口都有他使用的场合,它主要是为了区分在Spring内部在操作
过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如ListableBeanFactory接口表
示这些Bean是可列表的,而HierarchicalBeanFactory表示的是这些Bean是有继承关系的,也就是每
个Bean有可能有父Bean。AutowireCapableBeanFactory接口定义Bean的自动装配规则。这四个接口
共同定义了Bean的集合、Bean之间的关系、以及Bean行为。

BeanFactory 的类体系结构看似繁杂混乱,实际上由上而下井井有条,非常容易理解。

BeanFactory

    package org.springframework.beans.factory;

    public interface BeanFactory {
        //用来引用一个实例,或把它和工厂产生的Bean区分开
	 //就是说,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory
        String FACTORY_BEAN_PREFIX = "&";

        /*
         * 四个不同形式的getBean方法,获取实例
         */
        Object getBean(String name) throws BeansException;

        <T> T getBean(String name, Class<T> requiredType) throws
                BeansException;

        <T> T getBean(Class<T> requiredType) throws BeansException;

        Object getBean(String name, Object... args) throws BeansException;

        // 是否存在
        boolean containsBean(String name);

        // 是否为单实例
        boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

        // 是否为原型(多实例)
        boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

        // 名称、类型是否匹配
        boolean isTypeMatch(String name, Class<?> targetType)
                throws NoSuchBeanDefinitionException;

        // 获取类型
        Class<?> getType(String name) throws NoSuchBeanDefinitionException;

        // 根据实例的名字获取实例的别名
        String[] getAliases(String name);
    }

在BeanFactory里只对IOC容器的基本行为作了定义,根本不关心你的Bean是如何定义怎样加载的。正
如我们只关心工厂里得到什么的产品对象,至于工厂是怎么生产这些对象的,这个基本的接口不关心。

  • 4个获取实例的方法。getBean的重载方法。
  • 4个判断的方法。判断是否存在,是否为单例、原型,名称类型是否匹配。
  • 1个获取类型的方法、一个获取别名的方法。根据名称获取类型、根据名称获取别名。一目了
    然!

这10个方法,很明显,这是一个典型的工厂模式的工厂接口。

ListableBeanFactory
可将Bean逐一列出的工厂
public interface ListableBeanFactory extends BeanFactory {
    // 对于给定的名字是否含有
    boolean containsBeanDefinition(String beanName);

    // 返回工厂的BeanDefinition总数
    int getBeanDefinitionCount();

    // 返回工厂中所有Bean的名字
    String[] getBeanDefinitionNames();

    // 返回对于指定类型Bean(包括子类)的所有名字
    String[] getBeanNamesForType(Class<?> type);

    /*
     * 返回指定类型的名字
     * includeNonSingletons为false表示只取单例Bean,true则不是
     * allowEagerInit为true表示立刻加载,false表示延迟加载。
     * 注意:FactoryBeans都是立刻加载的。
     */
    String[] getBeanNamesForType(Class<?> type, boolean
            includeNonSingletons,
                                 boolean allowEagerInit);

    // 根据类型(包括子类)返回指定Bean名和Bean的Map
    <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;

    <T> Map<String, T> getBeansOfType(Class<T> type,
                                      boolean includeNonSingletons, boolean allowEagerInit)
            throws BeansException;

    // 根据注解类型,查找所有有这个注解的Bean名和Bean的Map
    Map<String, Object> getBeansWithAnnotation(
            Class<? extends Annotation> annotationType) throws
            BeansException;

    // 根据指定Bean名和注解类型查找指定的Bean
    <A extends Annotation> A findAnnotationOnBean(String beanName,
                                                  Class<A> annotationType);
}
  • 3个跟BeanDefinition有关的总体操作。包括BeanDefinition的总数、名字的集合、指定
    类型的名字的集合。

      这里指出,BeanDefinition是Spring中非常重要的一个类,每个BeanDefinition实例
    

都包含一个类在Spring工厂中所有属性。

  • 2个getBeanNamesForType重载方法。根据指定类型(包括子类)获取其对应的所有Bean名
    字。
  • 2个getBeansOfType重载方法。根据类型(包括子类)返回指定Bean名和Bean的Map。
  • 2个跟注解查找有关的方法。根据注解类型,查找Bean名和Bean的Map。以及根据指定Bean
    名和注解类型查找指定的Bean。

正如这个工厂接口的名字所示,这个工厂接口最大的特点就是可以列出工厂可以生产的所有实例。当
然,工厂并没有直接提供返回所有实例的方法,也没这个必要。它可以返回指定类型的所有的实例。而
且你可以通过getBeanDefinitionNames()得到工厂所有bean的名字,然后根据这些名字得到所有的
Bean。这个工厂接口扩展了BeanFactory的功能,作为上文指出的BeanFactory二级接口,有9个独有
的方法,扩展了跟BeanDefinition的功能,提供了BeanDefinition、BeanName、注解有关的各种操
作。它可以根据条件返回Bean的信息集合,这就是它名字的由来——ListableBeanFactory。

HierarchicalBeanFactory
分层的Bean工厂
public interface HierarchicalBeanFactory extends BeanFactory {
    // 返回本Bean工厂的父工厂
    BeanFactory getParentBeanFactory();

    // 本地工厂是否包含这个Bean
    boolean containsLocalBean(String name);
}
  • 第一个方法返回本Bean工厂的父工厂。这个方法实现了工厂的分层。
  • 第二个方法判断本地工厂是否包含这个Bean(忽略其他所有父工厂)。这也是分层思想的体
    现。
    这个工厂接口非常简单,实现了Bean工厂的分层。这个工厂接口也是继承自BeanFacotory,也是
    一个二级接口,相对于父接口,它只扩展了一个重要的功能——工厂分层。
AutowireCapableBeanFactory
自动装配的Bean工厂
public interface AutowireCapableBeanFactory extends BeanFactory {
    // 这个常量表明工厂没有自动装配的Bean
    int AUTOWIRE_NO = 0;
    // 表明根据名称自动装配
    int AUTOWIRE_BY_NAME = 1;
    // 表明根据类型自动装配
    int AUTOWIRE_BY_TYPE = 2;
    // 表明根据构造方法快速装配
    int AUTOWIRE_CONSTRUCTOR = 3;
    //表明通过Bean的class的内部来自动装配(有没翻译错...)Spring3.0被弃用。
    @Deprecated
    int AUTOWIRE_AUTODETECT = 4;

    // 根据指定Class创建一个全新的Bean实例
    <T> T createBean(Class<T> beanClass) throws BeansException;

    // 给定对象,根据注释、后处理器等,进行自动装配
    void autowireBean(Object existingBean) throws BeansException;

    // 根据Bean名的BeanDefinition装配这个未加工的Object,执行回调和各种后处理器。
    Object configureBean(Object existingBean, String beanName) throws
            BeansException;

    // 分解Bean在工厂中定义的这个指定的依赖descriptor
    Object resolveDependency(DependencyDescriptor descriptor, String
            beanName) throws BeansException;

    // 根据给定的类型和指定的装配策略,创建一个新的Bean实例
    Object createBean(Class<?> beanClass, int autowireMode, boolean
            dependencyCheck) throws BeansException;

    // 与上面类似,不过稍有不同。
    Object autowire(Class<?> beanClass, int autowireMode, boolean
            dependencyCheck) throws BeansException;

    /*
     * 根据名称或类型自动装配
     */
    void autowireBeanProperties(Object existingBean, int autowireMode,
                                boolean dependencyCheck)
            throws BeansException;

    /*
     * 也是自动装配
     */
    void applyBeanPropertyValues(Object existingBean, String beanName)
            throws BeansException;

    /*
     * 初始化一个Bean...
     */
    Object initializeBean(Object existingBean, String beanName) throws
            BeansException;

    /*
     * 初始化之前执行BeanPostProcessors
     */
    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean,
                                                       String beanName)
            throws BeansException;

    /*
     * 初始化之后执行BeanPostProcessors
     */
    Object applyBeanPostProcessorsAfterInitialization(Object existingBean,
                                                      String beanName)
            throws BeansException;

    /*
     * 分解指定的依赖
     */
    Object resolveDependency(DependencyDescriptor descriptor, String
            beanName,
                             Set<String> autowiredBeanNames, TypeConverter typeConverter)
            throws BeansException;
}
  1. 总共5个静态不可变常量来指明装配策略,其中一个常量被Spring3.0废弃、一个常量表示没有自动装配,另外3个常量指明不同的装配策略——根据名称、根据类型、根据构造方法。
    
  2. 8个跟自动装配有关的方法,实在是繁杂,具体的意义我们研究类的时候再分辨吧。
    
  3. 2个执行BeanPostProcessors的方法。
    
  4. 2个分解指定依赖的方法
    

这个工厂接口继承自BeanFacotory,它扩展了自动装配的功能,根据类定义BeanDefinition装配
Bean、执行前、后处理器等。

ConfigurableBeanFactory
复杂的配置Bean工厂
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory,
        SingletonBeanRegistry {
    String SCOPE_SINGLETON = "singleton"; // 单例
    String SCOPE_PROTOTYPE = "prototype"; // 原型

    /*
     * 搭配HierarchicalBeanFactory接口的getParentBeanFactory方法
     */
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws
            IllegalStateException;

    /*
     * 设置、返回工厂的类加载器
     */
    void setBeanClassLoader(ClassLoader beanClassLoader);

    ClassLoader getBeanClassLoader();

    /*
     * 设置、返回一个临时的类加载器
     */
    void setTempClassLoader(ClassLoader tempClassLoader);

    ClassLoader getTempClassLoader();

    /*
    * 设置、是否缓存元数据,如果false,那么每次请求实例,都会从类加载器重新加载(热加
    载)
    */
    void setCacheBeanMetadata(boolean cacheBeanMetadata);

    boolean isCacheBeanMetadata();//是否缓存元数据

    /*
     * Bean表达式分解器
     */
    void setBeanExpressionResolver(BeanExpressionResolver resolver);

    BeanExpressionResolver getBeanExpressionResolver();

    /*
     * 设置、返回一个转换服务
     */
    void setConversionService(ConversionService conversionService);

    ConversionService getConversionService();

    /*
     * 设置属性编辑登记员...
     */
    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);

    /*
     * 注册常用属性编辑器
     */
    void registerCustomEditor(Class<?> requiredType, Class<? extends
            PropertyEditor> propertyEditorClass);

    /*
     * 用工厂中注册的通用的编辑器初始化指定的属性编辑注册器
     */
    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);

    /*
     * 设置、得到一个类型转换器
     */
    void setTypeConverter(TypeConverter typeConverter);

    TypeConverter getTypeConverter();

    /*
     * 增加一个嵌入式的StringValueResolver
     */
    void addEmbeddedValueResolver(StringValueResolver valueResolver);

    String resolveEmbeddedValue(String value);//分解指定的嵌入式的值

    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);//设置一个Bean后处理器

    int getBeanPostProcessorCount();//返回Bean后处理器的数量

    void registerScope(String scopeName, Scope scope);//注册范围

    String[] getRegisteredScopeNames();//返回注册的范围名

    Scope getRegisteredScope(String scopeName);//返回指定的范围

    AccessControlContext getAccessControlContext();//返回本工厂的一个安全访问上下文

    void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);//从其他的工厂复制相关的所有配置

    /*
     * 给指定的Bean注册别名
     */
    void registerAlias(String beanName, String alias) throws
            BeanDefinitionStoreException;

    void resolveAliases(StringValueResolver valueResolver);//根据指定的StringValueResolver移除所有的别名

    /*
     * 返回指定Bean合并后的Bean定义
     */
    BeanDefinition getMergedBeanDefinition(String beanName) throws
            NoSuchBeanDefinitionException;

    boolean isFactoryBean(String name) throws
            NoSuchBeanDefinitionException;//判断指定Bean是否为一个工厂Bean

    void setCurrentlyInCreation(String beanName, boolean inCreation);//设置一个Bean是否正在创建

    boolean isCurrentlyInCreation(String beanName);//返回指定Bean是否已经成功创建

    void registerDependentBean(String beanName, String
            dependentBeanName);//注册一个依赖于指定bean的Bean

    String[] getDependentBeans(String beanName);//返回依赖于指定Bean的所欲Bean名

    String[] getDependenciesForBean(String beanName);//返回指定Bean依赖的所有Bean名

    void destroyBean(String beanName, Object beanInstance);//销毁指定的Bean

    void destroyScopedBean(String beanName);//销毁指定的范围Bean

    void destroySingletons(); //销毁所有的单例类
}
ConfigurableListableBeanFactory
BeanFactory的集大成者
public interface ConfigurableListableBeanFactory
        extends ListableBeanFactory, AutowireCapableBeanFactory,
        ConfigurableBeanFactory {
    void ignoreDependencyType(Class<?> type);//忽略自动装配的依赖类型

    void ignoreDependencyInterface(Class<?> ifc);//忽略自动装配的接口

    /*
     * 注册一个可分解的依赖
     */
    void registerResolvableDependency(Class<?> dependencyType, Object
            autowiredValue);

    /*
     * 判断指定的Bean是否有资格作为自动装配的候选者
     */
    boolean isAutowireCandidate(String beanName, DependencyDescriptor
            descriptor) throws NoSuchBeanDefinitionException;

    // 返回注册的Bean定义
    BeanDefinition getBeanDefinition(String beanName) throws
            NoSuchBeanDefinitionException;

    // 暂时冻结所有的Bean配置
    void freezeConfiguration();

    // 判断本工厂配置是否被冻结
    boolean isConfigurationFrozen();

    // 使所有的非延迟加载的单例类都实例化。
    void preInstantiateSingletons() throws BeansException;
}

  1. 2个忽略自动装配的的方法
    
  2. 1个注册一个可分解依赖的方法。
    
  3. 1个判断指定的Bean是否有资格作为自动装配的候选者的方法。
    
  4. 1个根据指定bean名,返回注册的Bean定义的方法。
    
  5. 2个冻结所有的Bean配置相关的方法。
    
  6. 1个使所有的非延迟加载的单例类都实例化的方法
    

    工厂接口 ConfigurableListableBeanFactory 同时继承了3个接口, ListableBeanFactory 、
    AutowireCapableBeanFactory 和 ConfigurableBeanFactory ,扩展之后,加上自有的这8
    个方法,这个工厂接口总共有83个方法,实在是巨大到不行了。这个工厂接口的自有方法总体上
    只是对父类接口功能的补充,包含了 BeanFactory 体系目前的所有方法,可以说是接口的集大成
    者。

BeanDefinitionRegistry
额外的接口,这个接口基本用来操作定义在工厂内部的BeanDefinition的。

public interface BeanDefinitionRegistry extends AliasRegistry {
    // 给定bean名称,注册一个新的bean定义
    void registerBeanDefinition(String beanName, BeanDefinition
            beanDefinition) throws BeanDefinitionStoreException;

    /*
     * 根据指定Bean名移除对应的Bean定义
     */
    void removeBeanDefinition(String beanName) throws
            NoSuchBeanDefinitionException;

    /*
     * 根据指定bean名得到对应的Bean定义
     */
    BeanDefinition getBeanDefinition(String beanName) throws
            NoSuchBeanDefinitionException;

    /*
     * 查找,指定的Bean名是否包含Bean定义
     */
    boolean containsBeanDefinition(String beanName);

    String[] getBeanDefinitionNames();//返回本容器内所有注册的Bean定义名称

    int getBeanDefinitionCount();//返回本容器内注册的Bean定义数目

    boolean isBeanNameInUse(String beanName);//指定Bean名是否被注册过。
}
ApplicationContext继承体系
体系结构图

在这里插入图片描述
ApplicationContext允许上下文嵌套,通过保持父上下文可以维持一个上下文体系。对于Bean的查找
可以在这个上下文体系中发生,首先检查当前上下文,其次是父上下文,逐级向上,这样为不同的
Spring应用提供了一个共享的Bean定义环境。

容器初始化流程源码分析

主流程源码分析

找入口

  • java程序入口
BeanFactory bf = new XmlBeanFactory("spring.xml");
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
  • web程序入口
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:spring.xml</param-value>
</context-param>
<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>
</listener>

注意:不管上面哪种方式,最终都会调 AbstractApplicationContext的refresh方法 ,而这个
方法才是我们真正的入口。

流程解析

  • AbstractApplicationContext的 refresh 方法
public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            // STEP 1: 刷新预处理
            prepareRefresh();
            // Tell the subclass to refresh the internal bean factory.
            // STEP 2:
            // a) 创建IoC容器(DefaultListableBeanFactory)
            // b) 加载解析XML文件(最终存储到Document对象中)
            // c) 读取Document对象,并完成BeanDefinition的加载和注册工作
            ConfigurableListableBeanFactory beanFactory =
                    obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            // STEP 3: 对IoC容器进行一些预处理(设置一些公共属性)
            prepareBeanFactory(beanFactory);
            try {
                // Allows post-processing of the bean factory in context subclasses.
                // STEP 4:
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
                // STEP 5: 调用BeanFactoryPostProcessor后置处理器对BeanDefinition处理
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
                // STEP 6: 注册BeanPostProcessor后置处理器
                registerBeanPostProcessors(beanFactory);
                // Initialize message source for this context.
                // STEP 7: 初始化一些消息源(比如处理国际化的i18n等消息源)
                initMessageSource();
                // Initialize event multicaster for this context.
                // STEP 8: 初始化应用事件广播器
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                // STEP 9: 初始化一些特殊的bean
                onRefresh();

                // Check for listener beans and register them.
                // STEP 10: 注册一些监听器
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                // STEP 11: 实例化剩余的单例bean(非懒加载方式)
                // 注意事项:Bean的IoC、DI和AOP都是发生在此步骤
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
                // STEP 12: 完成刷新时,需要发布对应的事件
                finishRefresh();
            } catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context
                            initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();
                // Reset 'active' flag.
                cancelRefresh(ex);
                // Propagate exception to caller.
                throw ex;
            } finally {// Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }
创建BeanFactory流程源码分析
找入口
AbstractApplicationContext类的 refresh 方法:
    // Tell the subclass to refresh the internal bean factory.
    // STEP 2:
    // a) 创建IoC容器(DefaultListableBeanFactory)
    // b) 加载解析XML文件(最终存储到Document对象中)
    // c) 读取Document对象,并完成BeanDefinition的加载和注册工作
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 主要是通过该方法完成IoC容器的刷新
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " +
                    beanFactory);
        }
        return beanFactory;
    }
流程解析
  • 进入AbstractApplication的 obtainFreshBeanFactory 方法:用于创建一个新的 IoC容器 ,这个 IoC容器 就是DefaultListableBeanFactory对象。
进入AbstractRefreshableApplicationContext的 refreshBeanFactory 方法:
  • 销毁以前的容器
  • 创建新的 IoC容器
  • 加载 BeanDefinition 对象注册到IoC容器中
protected final void refreshBeanFactory() throws BeansException {
    // 如果之前有IoC容器,则销毁
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 创建IoC容器,也就是DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            // 加载BeanDefinition对象,并注册到IoC容器中(重点)
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean
                    definition source for " + getDisplayName(), ex);
        }
    }
进入AbstractRefreshableApplicationContext的 createBeanFactory 方法
    protected DefaultListableBeanFactory createBeanFactory() {
        return new
                DefaultListableBeanFactory(getInternalParentBeanFactory());
    }
加载BeanDefinition流程分析
找入口
AbstractRefreshableApplicationContext类的 refreshBeanFactory 方法中第13行代码:
protected final void refreshBeanFactory() throws BeansException {
        // 如果之前有IoC容器,则销毁
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 创建IoC容器,也就是DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            // 加载BeanDefinition对象,并注册到IoC容器中(重点)
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean
                    definition source for " + getDisplayName(), ex);
        }
    }
BeanDefinition流程
|——AbstractRefreshableApplicationContext#refreshBeanFactory
|--AbstractXmlApplicationContext#loadBeanDefinitions:走了多个重载方法
|--AbstractBeanDefinitionReader#loadBeanDefinitions:走了多个重载方法
|--XmlBeanDefinitionReader#loadBeanDefinitions:走了多个重载方法
|--XmlBeanDefinitionReader#doLoadBeanDefinitions
|--XmlBeanDefinitionReader#registerBeanDefinitions
|--
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
|--#doRegisterBeanDefinitions
|--#parseBeanDefinitions
|--#parseDefaultElement
|--#processBeanDefinition
|--
BeanDefinitionParserDelegate#parseBeanDefinitionElement
|--
#parseBeanDefinitionElement
流程相关类的说明
  • AbstractRefreshableApplicationContext
    主要用来对BeanFactory提供 refresh 功能。包括BeanFactory的创建和 BeanDefinition 的定
    义、解析、注册操作。
  • AbstractXmlApplicationContext
    主要提供对于 XML资源 的加载功能。包括从Resource资源对象和资源路径中加载XML文件。
  • AbstractBeanDefinitionReader
    主要提供对于 BeanDefinition 对象的读取功能。具体读取工作交给子类实现。
  • XmlBeanDefinitionReader
    主要通过 DOM4J 对于 XML资源 的读取、解析功能,并提供对于 BeanDefinition 的注册功能。
  • DefaultBeanDefinitionDocumentReader
  • BeanDefinitionParserDelegate
流程解析
  • 进入AbstractXmlApplicationContext的loadBeanDefinitions方法:
    • 创建一个XmlBeanDefinitionReader,通过阅读XML文件,真正完成BeanDefinition的加
      载和注册。
    • 配置XmlBeanDefinitionReader并进行初始化。
    • 委托给XmlBeanDefinitionReader去加载BeanDefinition。
protected void loadBeanDefinitions(DefaultListableBeanFactory
                                               beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        // 给指定的工厂创建一个BeanDefinition阅读器
        // 作用:通过阅读XML文件,真正完成BeanDefinition的加载和注册
        XmlBeanDefinitionReader beanDefinitionReader = new
                XmlBeanDefinitionReader(beanFactory);
        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new
                ResourceEntityResolver(this));
        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
        // 委托给BeanDefinition阅读器去加载BeanDefinition
        loadBeanDefinitions(beanDefinitionReader);
    }

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)
            throws
            BeansException, IOException {
        // 获取资源的定位
        // 这里getConfigResources是一个空实现,真正实现是调用子类的获取资源定位的方法
        // 比如:ClassPathXmlApplicationContext中进行了实现
        // 而FileSystemXmlApplicationContext没有使用该方法
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            // XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
            reader.loadBeanDefinitions(configResources);
        }
        // 如果子类中获取的资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            // XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
            reader.loadBeanDefinitions(configLocations);
        }
    }
  • loadBeanDefinitions 方法经过一路的兜兜转转,最终来到了XmlBeanDefinitionReader的
    doLoadBeanDefinitions 方法:
    • 一个是对XML文件进行DOM解析;
    • 一个是完成BeanDefinition对象的加载与注册 。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource
            resource)
            throws BeanDefinitionStoreException {
        try {   
            // 通过DOM4J加载解析XML文件,最终形成Document对象
            Document doc = doLoadDocument(inputSource, resource);
            // 通过对Document对象的操作,完成BeanDefinition的加载和注册工作
            return registerBeanDefinitions(doc, resource);
        }
        //省略一些catch语句
        catch (Throwable ex) {
            ......
        }
    }
  • 此处我们暂不处理DOM4J加载解析XML的流程,我们重点分析BeanDefinition的加载注册流程
  • 进入XmlBeanDefinitionReader的 registerBeanDefinitions 方法:
    • 创建DefaultBeanDefinitionDocumentReader用来解析Document对象。
    • 获得容器中已注册的BeanDefinition数量
    • 委托给DefaultBeanDefinitionDocumentReader来完成BeanDefinition的加载、注册工
      作。
    • 统计新注册的BeanDefinition数量
    public int registerBeanDefinitions(Document doc, Resource resource) 
            throws
            BeanDefinitionStoreException {
        // 创建DefaultBeanDefinitionDocumentReader用来解析Document对象
        BeanDefinitionDocumentReader documentReader =
                createBeanDefinitionDocumentReader();
        // 获得容器中注册的Bean数量
        int countBefore = getRegistry().getBeanDefinitionCount();
        //解析过程入口,BeanDefinitionDocumentReader只是个接口
        //具体的实现过程在DefaultBeanDefinitionDocumentReader完成
        documentReader.registerBeanDefinitions(doc,
                createReaderContext(resource));
        // 统计注册的Bean数量
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }
  • 进入DefaultBeanDefinitionDocumentReader的 registerBeanDefinitions 方法:
    • 获得Document的根元素标签
    • 真正实现BeanDefinition解析和注册工作
    public void registerBeanDefinitions(Document doc, XmlReaderContext
            readerContext {
        this.readerContext = readerContext;
        logger.debug("Loading bean definitions");
        // 获得Document的根元素<beans>标签
        Element root = doc.getDocumentElement();
        // 真正实现BeanDefinition解析和注册工作
        doRegisterBeanDefinitions(root);
    }
  • 进入DefaultBeanDefinitionDocumentReader doRegisterBeanDefinitions 方法:
    • 这里使用了委托模式,将具体的BeanDefinition解析工作交给了
      BeanDefinitionParserDelegate去完成
    • 在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
    • 委托给BeanDefinitionParserDelegate,从Document的根元素开始进行BeanDefinition
      的解析
    • 在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
protected void doRegisterBeanDefinitions(Element root) {
        // Any nested <beans> elements will cause recursion in this method. In
        // order to propagate and preserve <beans> default-* attributes correctly,
        // keep track of the current (parent) delegate, which may be null. Create
        // the new (child) delegate with a reference to the parent for fallback purposes,
        // then ultimately reset this.delegate back to its original (parent) reference.
        // this behavior emulates a stack of delegates without actually necessitating one.
        
        // 这里使用了委托模式,将具体的BeanDefinition解析工作交给了
        BeanDefinitionParserDelegate去完成
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);
        if (this.delegate.isDefaultNamespace(root)) {
            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles =
                        StringUtils.tokenizeToStringArray(
                                profileSpec,
                                BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                if
                (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Skipped XML bean definition file due
                                to specified profiles[" + profileSpec +
                                "] not matching: " +
                                        getReaderContext().getResource());
                    }
                    return;
                }
            }
        }
        // 在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
        preProcessXml(root);
        // 委托给BeanDefinitionParserDelegate,从Document的根元素开始进行
        BeanDefinition的解析
        parseBeanDefinitions(root, this.delegate);
        // 在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
        postProcessXml(root);
        this.delegate = parent;
    }

Bean创建主流程分析

找入口

AbstractApplicationContext类的 refresh 方法:

    // Instantiate all remaining (non-lazy-init) singletons.
    // STEP 11: 实例化剩余的单例bean(非懒加载方式)
    // 注意事项:Bean的IoC、DI和AOP都是发生在此步骤
    finishBeanFactoryInitialization(beanFactory);

流程解析

Bean实例化流程分析
DI依赖注入流程分析
BeanWrapperImpl构造方法源码分析

BeanWrapperImpl构造方法
BeanWrapperImpl类有多个重载方法,下面的构造方法传入一个Object对象,此对象就是被
BeanWrapperImpl类所包装的bean

    public BeanWrapperImpl(Object object) {
        registerDefaultEditors();
        setWrappedInstance(object);
    }

构造方法的实现很简单
第一步在registerDefaultEditors()方法内部设置属性defaultEditorsActive值为true
第二步则调用setWrappedInstance(object)方法,进行初始化以及设置被包装的对象

setWrappedInstance(object)方法
此方法内部对BeanWrapperImpl类的一些重要属性进行了初始化,并创建了
TypeConverterDelegate类的实例作为类型转换处理对象。
在此之后,将对被包装bean进行内省分析,内省分析结果保存在cachedIntrospectionResults
属性中,此属性是CachedIntrospectionResults类的实例.
CachedIntrospectionResults类
CachedIntrospectionResults类用于对对象的Class进行内省分析,保存对象的
PropertyDescriptor信息,其静态方法

static CachedIntrospectionResults forClass(Class beanClass) throws
BeansException

在BeanWrapperImpl类中被调用,用于对BeanWrapperImpl类所包装的bean进行内省分析,并返回内省分析结果给BeanWrapperImpl

BeanWrapperImpl设置属性值源码分析

setPropertyValue(PropertyValue pv)方法
BeanWrapperImpl类有多个设置bean属性值的重载方法,此处以

public void setPropertyValue(PropertyValue pv) throws BeansException
    public void setPropertyValue(PropertyValue pv) throws BeansException {
        PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
        if (tokens == null) { ……………..BeanWrapperImpl nestedBw =
                null;
            try { //根据属性名获取BeanWrapImpl对象,支持多重属性的递归分析处理 
                nestedBw =
                        getBeanWrapperForPropertyPath(propertyName);
            } catch
            tokens = getPropertyNameTokens(getFinalPath(nestedBw,
                    propertyName)); //如果nestedBw等于this,则设置resolvedTokens属性值为
            tokens if (nestedBw == this) {
                pv.getOriginalPropertyValue().resolvedTokens = tokens;
            }
            nestedBw.setPropertyValue(tokens, pv);
        } else {
            setPropertyValue(tokens, pv);
        }
    }

上述方法根据tokens变量是否为null,有两个不同的分支。其中当tokens为null时,则会对属性
名进行递归调用分析处理,返回分析处理后的BeanWrapImpl对象nestedBw。如果
nestedBw==this,则会设置pv的resolvedTokens属性值,最后将调用nestedBw对象的设置属性
值方法设置属性
getBeanWrapperForPropertyPath方法
getBeanWrapperForPropertyPath方法用于对属性名称(包括多重属性)进行处理,并返回
BeanWrapperImpl对象。所支持的属性名称包括:多重属性(以.分隔)、数组集合map key属性
(以[]方式)。

    protected BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath) {
        //根据属性路径获取其第一个属性分隔符.的下标
        int pos =
                PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);
        //如果找到,则表示是有多重属性递归处理
        // Handle nested properties recursively.
        if (pos > -1) {
            //获取第一个属性分隔符前面的属性名称
            String nestedProperty = propertyPath.substring(0, pos);
            //获取第一个属性分隔符后面的字符串
            String nestedPath = propertyPath.substring(pos + 1);
            //获取第一个属性片断的BeanWrapperImpl对象nestedBw
            BeanWrapperImpl nestedBw = getNestedBeanWrapper(nestedProperty);
            //调用nestedBw的getBeanWrapperForPropertyPath方法,对第一个属性分隔符后面的属性字符串进行处理
            return nestedBw.getBeanWrapperForPropertyPath(nestedPath);
        }
        //否则,返回this对象本身
        else {
            return this;
        }
    }

在此方法中对嵌套类型的属性进行了分析,首先将处理第一个.前的属性,获取nestedBw对象。
然后再调用nestedBw对象的此方法递归处理第一个.后的其它属性,并返回处理结果。
getNestedBeanWrapper(nestedProperty)方法则根据nestedProperty获取嵌套的BeanWrapperImpl对象。
getPropertyNameTokens方法
getPropertyNameTokens方法内部用于对属性名全路径中最后一个.后的属性名称分析,返回
PropertyTokenHolder对象。
setPropertyValue(tokens, pv)方法
最终的设置属性的操作在此方法内部进行实现,此方法将最原始的属性值经过数组、集合类型属
性的处理和类型转换后得到转换后值convertedValue,并从内省信息中获取操作此属性的方法
writeMethod,用反射调用writeMethod将参数值convertedValue写入至被包装对象的目标属性
中。至此BeanWrapperImpl的对象设值操作处理完成。
BeanWrapperImpl对嵌套属性的支持
BeanWrapperImpl类通过其成员属性提供了一种支持嵌套属性的数据结构,下面是
BeanWrapperImpl类的成员:
属性类型及名称 说明
Object object 被BeanWrapper包装的对象
String nestedPath 当前BeanWrapper对象所属嵌套层次的属性名,最顶层的BeanWrapper此属性的值为空
Object rootObject 最顶层BeanWrapper所包装的对象
Map nestedBeanWrappers 缓存当前BeanWrapper的下一层属性的nestedPath和对应的BeanWrapperImpl对象,此BeanWrapperImpl所包装的对应是属性nestedPath的值

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值