Spring Bean 的创建是典型的工厂模式,在顶层的结构设计主要围绕着 BeanFactory 和 xxxRegistry 进行:

  • BeanFactory: 工厂模式定义了 IOC 容器的基本功能
  • BeanRegistry: 提供手动注册 BeanDefinition到容器中的方法

BeanFactory

BeanFactory作为最顶层的一个接口类,它定义了IOC容器的基本功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public interface BeanFactory {    

//用于取消引用实例并将其与FactoryBean创建的bean区分开来。例如,如果命名的bean是FactoryBean,则获取将返回Factory,而不是Factory返回的实例。
String FACTORY_BEAN_PREFIX = "&";

//根据bean的名字和Class类型等来得到bean实例
Object getBean(String name) throws BeansException;
Object getBean(String name, Class 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;

//返回指定bean的Provider
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

//检查工厂中是否包含给定name的bean,或者外部注册的bean
boolean containsBean(String name);

//检查所给定name的bean是否为单例/原型
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

//判断所给name的类型与type是否匹配
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

//获取给定name的bean的类型
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;

//返回给定name的bean的别名
String[] getAliases(String name);

}

BeanFactory 有三个子类:ListableBeanFactoryHierarchicalBeanFactoryAutowireCapableBeanFactory

  • **ListableBeanFactory**:该接口定义了访问容器中 Bean 基本信息的若干方法,如查看 Bean 的个数、获取某一类型 Bean 的配置名、查看容器中是否包括某一 Bean 等方法;
  • **HierarchicalBeanFactory**:父子级联 IoC 容器的接口,子容器可以通过接口方法访问父容器; 通过 HierarchicalBeanFactory 接口, Spring 的 IoC 容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的 Bean,但父容器不能访问子容器的 Bean。Spring 使用父子容器实现了很多功能,比如在 Spring MVC 中,展现层 Bean 位于一个子容器中,而业务层和持久层的 Bean 位于父容器中。这样,展现层 Bean 就可以引用业务层和持久层的 Bean,而业务层和持久层的 Bean 则看不到展现层的 Bean。
  • **ConfigurableBeanFactory**:是一个重要的接口,增强了 IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法;
  • ConfigurableListableBeanFactory: ListableBeanFactory 和 ConfigurableBeanFactory 的融合;
  • **AutowireCapableBeanFactory**:定义了将容器中的 Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法

BeanRegistry

BeanDefinitionRegistry 接口提供了向容器手工注册 BeanDefinition 对象的方法

BeanDefinition

Bean 对象存在依赖嵌套等关系,所以设计者设计了 BeanDefinition,它用来对 Bean 对象及关系定义;我们在理解时只需要抓住如下三个要点:

  • BeanDefinition 定义了各种 Bean 对象及其相互的关系
  • BeanDefinitionReader 这是 BeanDefinition 的解析器
  • BeanDefinitionHolder 这是 BeanDefination 的包装类,用来存储 BeanDefinition,name 以及 aliases 等。

ApplicationContext

ApplicationContext是IoC容器的接口,除了继承了BeanFactory的能力,还拓展了配置资源的加载、应用事件、国际化等功能

  • ApplicationEventPublisher:让容器拥有发布应用上下文事件的功能,包括容器启动事件、关闭事件等。
  • MessageSource:为应用提供 i18n 国际化消息访问的功能;
  • ResourcePatternResolver :资源模式解析接口,可以通过带前缀的 Ant 风格的资源文件路径装载 Spring 的配置文件。
  • LifeCycle:提供了 start()stop() 两个方法,主要用于控制异步处理过程。在具体使用时,该接口同时被 ApplicationContext 实现及具体 Bean 实现, ApplicationContext 会将 start/stop 的信息传递给容器中所有实现了该接口的 Bean,以达到管理和控制 JMX、任务调度等目的。

ApplicationContext体系

为什么设计这么多ApplicationContext?

第一,从类结构设计上看, 围绕着是否需要 Refresh 容器衍生出两个抽象类

  • GenericApplicationContext: 是初始化的时候就创建容器,往后的每次 refresh 都不会更改
  • AbstractRefreshableApplicationContextAbstractRefreshableApplicationContext 及子类的每次 refresh 都是先清除已有 (如果不存在就创建) 的容器,然后再重新创建,因此无法做到像 GenericApplicationContext 混合搭配从不同源头获取 bean 的定义信息

第二, 从加载的源来看(比如 xml,groovy,annotation 等), 衍生出众多类型的 ApplicationContext, 典型比如:

  • FileSystemXmlApplicationContext: 从文件系统下的一个或多个 xml 配置文件中加载上下文定义,也就是说系统盘符中加载 xml 配置文件。
  • ClassPathXmlApplicationContext: 从类路径下的一个或多个 xml 配置文件中加载上下文定义,适用于 xml 配置的方式。
  • AnnotationConfigApplicationContext: 从一个或多个基于 java 的配置类中加载上下文定义,适用于 java 注解的方式。
  • ConfigurableApplicationContext: 扩展于 ApplicationContext,它新增加了两个主要的方法: refresh()close(),让 ApplicationContext 具有启动、刷新和关闭应用上下文的能力。在应用上下文关闭的情况下调用 refresh() 即可启动应用上下文,在已经启动的状态下,调用 refresh() 则清除缓存并重新装载配置信息,而调用 close() 则可关闭应用上下文。

第三, 更进一步理解

***设计者在设计时 AnnotationConfigApplicationContext 为什么是继承 GenericApplicationContext***? 因为基于注解的配置,是不太会被运行时修改的,这意味着不需要进行动态 Bean 配置和刷新容器,所以只需要 GenericApplicationContext

而基于 XML 这种配置文件,这种文件是容易修改的,需要动态性刷新 Bean 的支持,所以 XML 相关的配置必然继承 AbstractRefreshableApplicationContext; 且存在多种 xml 的加载方式(位置不同的设计),所以必然会设计出 AbstractXmlApplicationContext, 其中包含对 XML 配置解析成 BeanDefination 的过程。

那么细心的你从上图可以***发现 AnnotationWebConfigApplicationContext 却是继承了 AbstractRefreshableApplicationContext 而不是 GenericApplicationContext***? 因为用户可以通过 ApplicationContextInitializer 来设置 contextInitializerClasses(context-param / init-param), 在这种情况下用户倾向于刷新 Bean 的,所以设计者选择让 AnnotationWebConfigApplicationContext 继承了 AbstractRefreshableApplicationContext

这一段解释封神,我直接复制粘贴😆

参考: