一. 概述
Spring容器通常指的是ApplicationContext的体系结构设计,即整个Spring框架的IOC功能,是通过ApplicationContext接口实现类来提供给应用程序使用的。应用程序通过ApplicationContext提供方法来间接与内部Bean工厂交互,如获取Bean对象实例等。
 
在Spring框架内部设计当中,ApplicationContext是Spring容器所管理、维护的beans对象的一个运行环境,即ApplicationContext包含一些功能组件:保存外部属性文件(properties文件,yml文件等)的属性键值对集合的Environment,容器配置的位置contextConfigLocation等等,用于创建bean对象需要的一些外部依赖;
而ApplicationContext内部最重要的组件,就是BeanFactory体系结构,ApplicationContext通过BeanFactory来维护Spring容器所管理的类对应的BeanDefintions,通过BeanFactory来获取类对象bean。与BeanFactory配套的就是ApplicationContext维护多个BeanFactoryPostProcessor,BeanPostProcessor来对BeanFactory进行拓展,对BeanFactory自身或所创建的bean对象实例进行加工、功能拓展,实现整体设计的高拓展性。
 
二. BeanFactory接口设计
 
BeanFactory
顶层接口,主要提供getBean方法,从该BeanFactory获取给定beanName,对应的bean对象实例;
 
ListableBeanFactory
继承于BeanFactory,主要提供根据给定条件,如type,Annotation,获取对应的所有beans列表的接口;
 
HierarchicalBeanFactory
继承于BeanFactory,提供获取parentBeanFactory的方法,实现BeanFactory的层次化功能;
 
ConfigurableBeanFactory
继承于HierarchicalBeanFactory接口,主要提供对BeanFactory进行相关配置的接口,如类加载器classLoader,beanPostProcessor,类型转换器,属性编辑器等在加载、创建和初始化bean实例时,需要用到的一些功能组件;
 
AutowireCapableBeanFactory
继承于BeanFactory,主要提供对于BeanFactory创建的bean,使用autowire的方式对其所依赖的beans进行依赖注入。
 
接口具体实现类
1. DefaultListableBeanFactory
BeanFactory接口体系的默认实现类,实现以上接口的功能,提供BeanDefinition的存储map,Bean对象对象的存储map。
其中Bean对象实例的存储map,定义在FactoryBeanRegistrySupport,FactoryBeanRegistrySupport实现了SingletonBeanRegistry接口,而DefaultListableBeanFactory的基类AbstractBeanFactory,继承于FactoryBeanRegistrySupport。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { ... /** Map from serialized id to factory instance. */
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<>(8); ... /** Map from dependency type to corresponding autowired value. */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16); /** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); /** Map of singleton and non-singleton bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64); /** Map of singleton-only bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64); /** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256); /** List of names of manually registered singletons, in registration order. */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16); /** Cached array of bean definition names in case of frozen configuration. */
@Nullable
private volatile String[] frozenBeanDefinitionNames; /** Whether bean definition metadata may be cached for all beans. */
private volatile boolean configurationFrozen = false; ... }
2. StaticListableBeanFactory
  • 用于存储给定的bean对象实例,不支持动态注册功能,是ListableBeanFactory接口的简单实现。

public class StaticListableBeanFactory implements ListableBeanFactory {

    /** Map from bean name to bean instance. */
private final Map<String, Object> beans; ... }
Bean的获取与注册的接口设计隔离
 
以上BeanFactory接口层次主要是以Bean的获取为主的设计。而注册是在BeanDefinitionRegistr和SingletonBeanRegistry中设计的。
 
 
bean的获取
在BeanFactory的接口继承体系中,主要是提供获取bean,如getBean;列举bean,如ListableBeanFactory;提供BeanFactory创建bean需要的组件的ConfigurableBeanFactory;以及对bean注入其他beans的
 
AutowireCapableBeanFactory。
但是没有提供注册bean的方法声明,即将BeanDefinition注册到BeanFactory实现类内部维护的ConcurrentHashMap类型的map中。
 
bean的注册
1. BeanDefinition的注册
提供BeanDefinition注册功能的是BeanDefinitionRegistry接口,在这个接口定义注册beanDefinition到BeanFactory的方法声明。
BeanFactory的实现类会实现BeanDefinitionRegistry,并实现BeanDefinitionRegistry接口的registerBeanDefinition系列方法来将给定的BeanDefinition注册到BeanFactory中。
 
2. Bean对象实例的注册
在SingletonBeanRegistry接口的实现类中提供存储的map和注册方法,BeanFactory实现SingletonBeanRegistry接口。
 
三. BeanDefinitionRegistry接口
 
注册BeanDefinitions。提供registerBeanDefinition,removeBeanDefinition等方法,用来从BeanFactory注册或移除BeanDefinition。
通常BeanFactory接口的实现类需要实现这个接口。
实现类(通常为BeanFactory接口实现类)的对象实例,被DefinitionReader接口实现类引用,DefinitionReader将BeanDefintion注册到该对象实例中。
四. SingletonBeanRegistry接口
用于注册单例Bean对象实例,实现类定义存储Bean对象实例的map,BeanFactory的类层次结构中需要实现这个接口,来提供Bean对象的注册和从Bean对象实例的map获取bean对象。
 
/**
* Support base class for singleton registries which need to handle
* {@link org.springframework.beans.factory.FactoryBean} instances,
* integrated with {@link DefaultSingletonBeanRegistry}'s singleton management.
*
* <p>Serves as base class for {@link AbstractBeanFactory}.
*
* @author Juergen Hoeller
* @since 2.5.1
*/
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry { /** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16); ... }
五. BeanFactoryPostProcessor接口设计
 
BeanFactory后置处理器,在BeanFactory创建好,加载好其所包含的所有beanDefinitions,但是还没有实例化bean之前,执行,具体为调用postProcessBeanFactory方法。ApplicationContext会自动检测当前存在的BeanFactoryPostProcessors,并在创建bean实例之前执行。除此之外也可以对BeanFactory进行其他拓展实现。
 
典型用实现类和用途:
1.ConfigurationClassPostProcessor,用于从BeanFactory中检测使用了@Configuration注解的类,对于这些类对应的BeanDefinitions集合,遍历并依次交给ConfigurationClassParser,ConfigurationClassBeanDefinitionReader处理,分别是处理与@Configuration同时使用的其他注解和将类内部的使用@Bean注解的方法,生成BeanDefinition,注册到BeanFactory。
 
2.BeanDefinition属性填充、修改:在postProcessBeanFactory方法中,可以对beanFactory所包含的beanDefinitions的propertyValues和构造函数参数值进行修改,如使用PropertyPlaceHolderConfigurer来对BeanDefinition的propertyValues的占位符进行填充、赋值。或者使用PropertyResourceConfigurer获取config文件中属性,对BeanDefinitions的相关属性进行赋值或者值覆盖。
 
六. BeanPostProcessor接口设计
 
Bean后置处理器,主要是可以对新创建的bean实例进行修改,提供了一个类似于hook机制,对创建好的bean对象实例进行修改。ApplicationContext会自动检测当前存在的beanPostProcessors,并应用在创建的bean实例上。
 
核心方法
postProcessBeforeInitialization:在创建好bean实例,但是在任何初始化回调执行之前,如InitializingBean的afterPropertiesSet,先执行该方法。
postProcessAfterInitialization:在创建好bean实例,并且所有的初始化回调都执行完了,如InitializingBean的afterPropertiesSet,再执行该方法。
 
注解处理相关的BeanPostProcessor
 
通常用于在创建好bean对象实例后,处理这个bean上面的注解。同时也可以对bean对象进行其他功能拓展。
 
BeanPostProcessor的注册
 
1.定义:在注解配置工具类AnnotationConfigUtils的静态方法registerAnnotationConfigProcessors方法中,定义注解的处理器的注册逻辑。
2.调用:在BeanFactoryPostProcessor中调用这个静态方法来完成将特定的BeanPostProcessor实现类,注册到ApplicationContext的BeanPostProcessor列表。
 
 
1.AutowiredAnnotationBeanPostProcessor:处理bean对象的依赖注入关系,即从BeanFactory获取该bean所依赖的bean,然后注入到该bean对应的成员变量中。
2.CommonAnnotationBeanPostProcessor:该bean中所使用了的JDK定义的注解的处理,如方法中的@PostConstruct,@PreDestroy,成员变量上的@Resource等。
3.PersistenceAnnotationBeanPostProcessor(JPA时添加):JPA相关bean的持久化处理。
 
七. BeanDefinitionReader接口
 
从xml文件、类路径下使用了@Component系列注解的类、或者从@Configuration注解的配置类,获取BeanDefintiions,然后注册到BeanFactory中。
 
1. XmlBeanDefinitionReader:基于XML文件
读取解析xml文件,通过Parser解析xml文件的标签。
针对beans标签,生成对应的BeanDefintions,然后注册到BeanFactory中。
针对其他有特殊功能的标签,如context:component-scan,context:anotation-config,还可以生成BeanFactoryPostProcessor,BeanPostProcessor接口实现类的bean等;除了可以生成BeanDefinitions之外,还可以实现其他功能。
 
NamespaceHandler:XML标签名称空间处理器
 
被XmlBeanDefinitionReader使用,XmlBeanDefinitionReader在处理每个XML标签名称空间的时候,如applicationContext.xml的context:,mvc:,通过一个DefaultNamespaceHandlerResolver来获取对应的NamespaceHandler实现类,然后通过这个NamespaceHandler实现类,进一步获取该命名空间的内部标签对应的BeanDefinitionParser实现类。
 
BeanDefinitionDocumentReader
 
被XmlBeanDefinitionReader使用,专门用于处理xml文件的beans标签的标签处理器。即XmlBeanDefinitionReader读取xml文件,创建Document对象,然后交给BeanDefinitionDocumentReader处理。
 
BeanDefinitionDocumentReader解析Document对象的Element节点,然后创建BeanDefinitions集合,通过XmlBeanDefinitionReader注册到XmlBeanDefinitionReader所在的BeanFactory。
 
2. AnnotatedBeanDefinitionReader:注册指定的类列表annotatedClasses
 
可以使用编程方法,显示指定将哪些类需要注册到BeanFactory。
 
主要是被AnnotationConfigApplicationContext使用,即基于注解配置的ApplicationContext,这是SpringBoot的默认ApplicationContext。典型使用为:先获取所有使用了@Configuration注解的类,然后通过AnnotatedBeanDefinitionReader生成与这些类对应的BeanDefinitions,并注册到BeanFactory。
 
3. ClassPathBeanDefinitionScanner:注册指定的basePackages下面的类
 
扫描指定类路径(包)下面的类,检测是否存在@Component注解及其子注解,从而生成BeanDefinition,然后注册到BeanFactory。
 
没有实现BeanDefinitionReader接口,但基于相同的设计思路:BeanDefinitionReader。
 
与AnnotatedBeanDefinitionReader一样,都是获取指定类,生成该类的BeanDefinition注册到BeanFactory,而不是像xml文件一样已经通过bean标签显示说明这个就是bean。
 
也是主要是被AnnotationConfigApplicationContext使用。与其他两种也是基于basePackages类路径扫描的方式不同之处为:
    
     1.context:component-scan标签:基于XML的ApplicationContext,实现类路径扫描,底层使用ComponentScanBeanDefinitionParser这个parser来处理。
     2.@ComponentScan:对于处理@Configuration配置类上面的@ComponentScan注解,则是通过ComponentScanAnnotationParser来处理的。
 
4. ConfigurationClassBeanDefinitionReader:基于@Configuration注解的类配置
 
处理@Configuration注解的配置类,加在这些配置类上面的注解,即与@Configuration一起使用的注解,如@ComponentScan,@PropertySource,@Import,@Profile等。
 
ConfigurationClassBeanDefinitionReader主要被ConfigurationClassPostProcessor调用,ConfigurationClassPostProcessor为BeanFactoryPostProcessor,详细可以看我的另外一篇文章:Spring基于@Configuration的类配置的内部源码实现
八. BeanDefinitionParser接口
 
xml文件的标签的解析处理器,通过实现 BeanDefinitionParser接口,来针对每个标签进行特定。
 
典型用途包括:生成BeanDefintion对象,或BeanFactoryPostProcessor对象,或BeanPostProcessor对象,或者为针对标签定义特定的功能,自定义该标签的用途。
 
Parser可以同时生成这三种类型中的一个或多个。如ComponentScanBeanDefinitionParser既生成BeanDefinitions,又生成ConfigurationClassPostProcessor(BeanFactoryPostProcessor接口实现类)。AnnotationConfigBeanDefinitionParser既生成BeanPostProcessor,又生成ConfigurationClassPostProcessor。
 
1. 直接创建BeanDefintion
 
DefaultBeanDefinitionDocumentReader:xml文件解析
 
本身不是BeanDefinitionParser接口的实现类,而是利用BeanDefinitionParser接口的实现类,解析xml文件的beans标签,及其里边嵌套的bean标签,获取BeanDefinitions。
 
ComponentScanBeanDefinitionParser
 
处理xml文件的context:component-scan标签,扫描basePackages属性指定的路径下面的类,检测并获取使用了@Component注解及其子注解的类,生成对应的BeanDefinitions。
 
ComponentScanAnnotationParser
 
 
处理@ComponentScan注解,与ComponentScanBeanDefinitionParser功能一样,一般是与@Configuration注解一起使用。在ConfigurationClassParser中创建ComponentScanAnnotationParser对象实例并在parse方法中调用,ConfigurationClassParser为处理@Configuration注解的类。
 
2. 创建BeanFactoryPostProcessor
 
ConfigurationClassPostProcessor:间接创建BeanDefinition
ConfigurationClassPostProcessor是一个BeanFactoryPostProcessor接口的实现类。
在ComponentScanBeanDefinitionParser和AnnotationConfigBeanDefinitionParser中会创建ConfigurationClassPostProcessor对象实例:这样由这些parser创建的BeanDefinitions,就可以被ConfigurationClassPostProcessor进一步处理,创建更多的BeanDefintions。
   
    1.ComponentScanBeanDefinitionParser:对应context:component-scan,在parse方法调用;
    2.AnnotationConfigBeanDefinitionParser:对应context:annotation-config,在parse方法调用;
    3.ClassPathBeanDefinitionScanner:在scan方法调用,该类在AnnotationConfigApplicationContext中使用;
    4.AnnotatedBeanDefinitionReader:在构造函数调用,该类在AnnotationConfigApplicationContext中使用。
 
从BeanFactory的BeanDefintions集合,过滤获取使用了@Configuration注解的类,然后从这些类的@Bean方法获取BeanDefintions。
3. 创建BeanPostProcessor
 
AnnotationConfigBeanDefinitionParser:处理context:annotation-config标签,产生相关的BeanPostProcessor:
 
ComponentScanBeanDefinitionParser:处理xml文件的context:component-scan标签。
 
以上两个parser都会产生以下两个BeanPostProcessor:
     1.CommonAnnotationBeanPostProcessor:处理bean对象及其方法中的JDK自身的注解;
     2.AutowiredAnnotationBeanPostProcessor:bean对象的依赖注入处理,如@Autowired。
 
4. 自定义功能拓展
可以通过自定义标签和自定义Parser接口的实现类,并结合NamespaceHandler来实现自动融入spring框架。如dubbo框架就利用了这个特性来实现自动融入spring框架。
 
 
获取更多学习资料,可以加群:473984645或扫描下方二维码
 

Spring IOC源码分析(二):Bean工厂体系结构设计的更多相关文章

  1. Spring Ioc源码分析系列--Bean实例化过程(二)

    Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...

  2. Spring Ioc源码分析系列--Bean实例化过程(一)

    Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...

  3. Spring Ioc源码分析系列--容器实例化Bean的四种方法

    Spring Ioc源码分析系列--实例化Bean的几种方法 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到bean真正通过那些方式实例化出来的时候,并没有继续分 ...

  4. Spring Ioc源码分析系列--自动注入循环依赖的处理

    Spring Ioc源码分析系列--自动注入循环依赖的处理 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到Spring创建bean出现循环依赖的时候并没有深入去分 ...

  5. Spring Ioc源码分析系列--@Autowired注解的实现原理

    Spring Ioc源码分析系列--@Autowired注解的实现原理 前言 前面系列文章分析了一把Spring Ioc的源码,是不是云里雾里,感觉并没有跟实际开发搭上半毛钱关系?看了一遍下来,对我的 ...

  6. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  7. Spring Ioc源码分析系列--Ioc的基础知识准备

    Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...

  8. Spring Ioc源码分析系列--Ioc源码入口分析

    Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...

  9. Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析

    Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...

  10. Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理

    Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...

随机推荐

  1. Haproxy+Percona-XtraDB-Cluster 集群

    Haproxy介绍 Haproxy 是一款提供高可用性.负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费.快速并且可靠的一种解决方案. HAProxy特别适用 ...

  2. vue中按需引入mint-UI报Error: .plugins[3][1] must be an object, false, or undefined

    { "presets": ["@babel/preset-env", "@babel/preset-react"], "plugi ...

  3. python while循坏和for循坏

    while循坏 while 条件: 条件成立,执行循坏体(注意,while循坏必须有结束条件,不然会进入死循坏) 简单做个演示: # -*- coding:utf-8 -*- # Author:覃振鸿 ...

  4. Java面试宝典(1)Java基础部分

    Java面试宝典 题目,日积月累,等到出去面试时,一切都水到渠成,面试时就自然会游刃有余了. 答题时,先答是什么,再答有什么作用和要注意什么(这部分最重要,展现自己的心得) 答案的段落分别,层次分明, ...

  5. bzoj [POI2015]Myjnie

    [POI2015]Myjnie Time Limit: 40 Sec Memory Limit: 256 MBSec Special Judge Description 有n家洗车店从左往右排成一排, ...

  6. Codeforces New Year and Arbitrary Arrangement

    New Year and Arbitrary Arrangement time limit per test2 seconds You are given three integers k, pa a ...

  7. LeetCode Array Easy 27. Remove Element 解题

    Given an array nums and a value val, remove all instances of that value in-place and return the new ...

  8. OpenCV的安装与配置

    1.去官网下载opencv,在本教程中选用的时opencv3.4.1,其他版本的配置方法异曲同工.下载链接http://opencv.org/releases.html,选择sources版本 2.解 ...

  9. idea激活教程,最新!!!

    1.下载破解补丁(关键). 破解补丁:JetbrainsIdesCrack-4.2-release.jar百度云地址:https://pan.baidu.com/s/18ovphd7sm7oYXQb4 ...

  10. HttpClient异常处理手册

    HttpClient异常处理手册 开源中国 发表于 2014-08-26 19:44:06 异常处理 HttpClient的使用者在执行HTPP方法(GET,PUT,DELETE等),可能遇到会两种主 ...