前言
在 spring 中,任何实现了 BeanFactory 接口的类都可以视为容器,它是 IOC 功能实现的核心,用于完成类实例从加载到销毁的整个生命周期的控制,这些被 spring 所管理的实例统称为 bean。
根据抽象层级的不同,容器又分为 BeanFactory 的直接实现,与基于 BeanFactory 的扩展实现 ApplicationContext,后者在前者的基础继承了 ResourceLoader和EnvironmentCapable接口,因而具备从某类运行环境的资源中直接加载 bean 的能力。
ApplicationContext 最常用的两个实现 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext ,前者用于从项目路径下根据 xml 文件加载 bean,而后者通过扫描类注解完成 bean 的加载。这两者 ApplicationContext 实际上就对应了我们所熟悉的两类配置方式,前者就是传统的 xml 配置,后者则是通过 @Component 与 @Bean 等注解对 bean 进行配置。
本文将基于 spring 源码 5.2.x 分支,基于 BeanFactory 与 ApplicationContext 两大接口,介绍 spring 的两类容器的结构体系。
一、BeanFactory 接口体系
总览 BeanFactory 体系,按照接口的抽象层次,大体可以分层四层:
- 第一层:
BeanFactory; - 第二层:
HierarchicalBeanFactory,ListableBeanFactory,AutowireCapableBeanFactory; - 第三层:
ConfigurableBeanFactory,此外还有一个关联性较强SingletonBeanRegistry; - 第四层:
ConfigurableListableBeanFactory;
1、BeanFactory
BeanFactory 是整个容器体系最顶层的接口,它的内容如下:
1 | public interface BeanFactory { |
我们可以直接从 BeanFactory 提供的方法看出,BeanFactory 定义了容器的一些基本能力:
- 容器可以根据名称、类型、构造函数这三个要素,单独或两两组合的的获得一个 bean;
- 容器获取的 bean 可以是单例多种多例的;
- 容器中的 bean 可以拥有多个名称;
2、分层工厂,批量工厂,自动装配工厂
BeanFactory 存在两个子接口 HierarchicalBeanFactory 和 ListableBeanFactory,它们进一步的扩展了容器的能力。
分层工厂 HierarchicalBeanFactory
HierarchicalBeanFactory 接口用于表示一个多集嵌套的 BeanFactory:
1 | public interface HierarchicalBeanFactory extends BeanFactory { |
批量工厂 ListableBeanFactory
ListableBeanFactory 接口定义了容器根据类型、名称或类上的注解批量的获取 bean 或 bean 名称的能力:
1 | public interface ListableBeanFactory extends BeanFactory { |
根据注释,当一个类同时实现了 HierarchicalBeanFactory 和 ListableBeanFactory 接口时,ListableBeanFactory 中的方法是不会考虑到父工厂的,也就是说,spring 中的 ListableBeanFactory 接口表示的能力只针对当前实现它的类。
自动装配工厂 AutowireCapableBeanFactory
AutowireCapableBeanFactory 如同他的名称一样,用于为容器关联的 bean 提供自动装配功能:
1 | public interface AutowireCapableBeanFactory extends BeanFactory { |
比较值得注意的是,通过 AutowireCapableBeanFactory 定义的 API 不难看出,只要能获得对应的实例,我们是可以手动的对非 spring 托管的 bean 进行依赖注入的。
3、分层配置工厂
BeanFactory 的三级接口为 ConfigurableBeanFactory,它实现了 HierarchicalBeanFactory 和 SingletonBeanRegistry接口。
从字面上理解,它是一个可配置的 BeanFactory,它不仅支持 BeanFactory 分层,还支持以单例的方式操作 bean。它是整个 BeanFactory 体系中最重要的一环,通过这个接口,spring 通过该接口规定了一个 BeanFactory 应该具备以及可以从中获取哪些可配置的组件与参数。
这里我们先了解一下 SingletonBeanRegistry 接口,这个接口定义了容器根据名称注册或获取 bean 单例的能力:
1 | public interface SingletonBeanRegistry { |
然后回到 ConfigurableBeanFactory ,它在 HierarchicalBeanFactory 的基础上补充了大量的方法:
1 | public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { |
这个接口定义了非常多的 API,按照用途来说,这些 API 大概分为三类:
- bean 的管理方法:包括 bean 依赖状态与生命周期的获取,bean 的销毁,bean 作用域域、定义信息与别名的操作;
- bean 创建过程中使用组件的配置:包括字符串解析器,类加载器,类型转换器,属性注册表,bean 的后置处理器等组件的配置;
- 工厂本身状态的一些操作:包括父工程配置,工厂间依赖的拷贝,以及访问控制等。
4、批量分层配置工厂
ConfigurableListableBeanFactory 是 BeanFactory 体系的第四级接口,也是最后一级接口。它继承了 ConfigurableBeanFactory、ListableBeanFactory与AutowireCapableBeanFactory 接口,因此它具备到目前为止 BeanFactory 前三级接口定义的全部能力。
它表示了一个可以配置的,允许按单例或多例操作 bean,支持自动装配 bean,并且可以根据 bean 的名称、类型或者类上注解批量获取 bean 的超级 bean 工厂。
它在上述功能的基础上,又针对各接口提供的功能定义了一些新的补充方法:
1 | public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory { |
二、ApplicationContext 接口体系
严格来说,ApplicationContext 是 BeanFactory 的子类,或者说,BeanFactory 是其组成的一部分。但是由于其附加了很多 BeanFactory 所不具备的功能,因此一般将其与 BeanFactory 体系分开看待。
ApplicationContext 有 web 环境上下文与非 web 环境上下文的两个实现体系,单纯按接口层次分为三层:
- 第一层:
ApplicationContext; - 第二层:
WebApplicationContext和ConfigurableApplicationContext; - 第三层:
ConfigurableApplicationContext;
1、ApplicationContext
ApplicationContext 接口是基于 BeanFactory 的进一步实现,它同时实现了 EnvironmentCapable,ListableBeanFactory,HierarchicalBeanFactory,MessageSource,ApplicationEventPublisher 以及 ResourcePatternResolver 接口。相较 BeanFactory ,它的功能要更加强大。
ApplicationContext 继承的各个接口分别对应它提供各项功能:
HierarchicalBeanFactory与ListableBeanFactory:提供像BeanFactory一样操作 bean 的功能;ApplicationEventPublisher:提供向监听器发布事件的能力;ResourcePatternResolver与EnvironmentCapable:提供选择性的某个特定环境的文件资源中加载配置的能力;MessageSource:提供解析消息并支持国际化配置的能力;
结合它提供的功能和它的名称,我们可以大概了解,与 BeanFactory 专门用于操作 bean 不同,ApplicationContext 用于提供 spring 程序在某个特定环境运行时所具备的全部信息的“上下文”对象,它之于 BeanFactory ,就像带各种功能的超级保温杯之于普通的水杯。
它定义的方法如下:
1 | public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { |
这里可以看到,虽然 ApplicationContext 没继承 AutowireCapableBeanFactory 接口,但是他依然可以通过方法获取到对应的装配工厂。
2、web 应用上下文与可配置上下文
WebApplicationContext
WebApplicationContext 是 web 环境的上下文,该上下文几乎没有可配置项,主要用于配置 Servlet 上下文:
1 | public interface WebApplicationContext extends ApplicationContext { |
ConfigurableApplicationContext
ConfigurableApplicationContext 表示一个可以配置的上下文容器,与 WebApplicationContext 不同,它提供了一些参数和属性的配置方法:
1 | public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable { |
它有一个通用可配置上下文的实现类:GenericApplicationContext,在非 web 环境中,该实现类的两个子类是最经常用到的:
GenericXmlApplicationContext:基于 xml 配置文件配置的上下文;AnnotationConfigApplicationContext:基于注解配置的上下文;
3、可配置的web应用上下文
ConfigurableApplicationContext 接口同时继承了 WebApplicationContext 和 ConfigurableApplicationContext,代表了一个可以配置的 web 上下文容器:
1 | public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext { |
一般 web 环境下实例化的上下文都为该接口的实例。
三、总结
在 spring 中,容器分为两大类:BeanFactory 和 ApplicationContext。
BeanFactory
其中,BeanFactory 是纯粹的用于管理 bean 对象生命周期的容器,它的接口体系分为四层:
BeanFactory接口本身,是容器的最高层抽象;HierarchicalBeanFactory:分层工厂,表示一个存在层级关系的容器;ListableBeanFactory:批量工厂,表示一个允许根据名称、类型或类注解等属性批量的操作 bean 的容器;AutowireCapableBeanFactory:自动装配工厂,表示一个可以关联需要自动装配的 bean 的容器;ConfigurableBeanFactory:分层配置工厂 ,是HierarchicalBeanFactory和SingletonBeanRegistry接口的组合,表示一个分层的、可以以单例模式操作 bean,并且允许调整配置的容器;ConfigurableListableBeanFactory:可配置的批量工厂,是ConfigurableBeanFactory与AutowireCapableBeanFactory接口的组合,具备BeanFactory体系中的全部能力。
ApplicationContext
ApplicationContext 是基于 BeanFactory 的扩展,它实现了其他的接口,因此具有一些 BeanFactory 不具备的功能:
ApplicationEventPublisher:提供向监听器发布事件的功能;ResourcePatternResolver与EnvironmentCapable:提供选择性的某个特定环境的文件资源中加载配置的功能;MessageSource:提供解析消息并支持国际化配置的功能;
从层次来说,ApplicationContext 主要分为三层:
ApplicationContext接口本身,是基于BeanFactory接口的扩展,是整个应用上下文体系的最顶层接口;WebApplicationContext:web 应用上下文,用于承载ServletContext;ConfigurableApplicationContext:用于非 web 环境下的可配置应用上下文;ConfigurableApplicationContext:可配置的 web 应用上下文,同时继承了WebApplicationContext和ConfigurableApplicationContext接口,代表了一个可以配置的 web 上下文容器。在一般的 web 环境中启动的都是该上下文的实例。