一. 概述
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. Java并发编程教程

    Java是一种多线程编程语言,我们可以使用Java来开发多线程程序. 多线程程序包含两个或多个可同时运行的部分,每个部分可以同时处理不同的任务,从而能更好地利用可用资源,特别是当您的计算机有多个CPU ...

  2. VS2008中编译运行MFC应用程序时,出现无法启动程序,因为计算机中丢失mfc90ud.dll的解决方案

     解决方法:"工具"->"选项"->"项目和解决方案"->"VC++目录",在可执行文件栏中加上如 ...

  3. 转 MySQL乐观锁和悲观锁

    悲观锁(Pessimistic Lock) 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁.传统的关系型数据库 ...

  4. export的用法

    定义环境变量并且赋值 # export MYENV= //定义环境变量并赋值 # export -p declare -x HOME=“/root“ declare -x LANG=“zh_CN.UT ...

  5. Django中的缓存机制

    概述       对于中等流量网站来说,尽可能的减少开销是必要的.缓存数据就是为了保存那些需要很多计算资源大的结果,这样的的话就不必在下次重复消耗计算资源.     Django自带了一个健壮的缓存系 ...

  6. 【外】001-python3之zip函数

    zip函数语法格式zip(可迭代对象1, 可迭代对象2, ... ,可迭代对象n) 函数接收任意个可迭代对象作为参数, 将所有对象中对应位置上的元素分别打包在一起组成一个tuple, 并将所有的tup ...

  7. CreateFile的内部实现

    今天想看看CreateFile的内部实现,不过网上没有想要的资料,都只是对参数分析了一下.找了找WRK源码,找到CreateFile的源码自己来分析一下. HANDLE WINAPI CreateFi ...

  8. PHP-缺失的第一个正数

    给定一个未排序的整数数组,找出其中没有出现的最小的正整数. 示例 1: 输入: [1,2,0]输出: 3示例 2: 输入: [3,4,-1,1]输出: 2示例 3: 输入: [7,8,9,11,12] ...

  9. string参考

    #include <iostream> #include <string.h> class string { private: char *data; public: stri ...

  10. 分考场(np完全问题,回溯法)

    问题描述 n个人参加某项特殊考试. 为了公平,要求任何两个认识的人不能分在同一个考场. 求是少需要分几个考场才能满足条件. 输入格式 第一行,一个整数n(1<n<100),表示参加考试的人 ...