文章目录
容器启动
Spring 的容器初始化,如new ClassPathXmlApplicationContext("spring-context.xml")
,内部调用 AbstractApplicationContext 的 refresh()
方法。该方法定义了 Spring 容器在加载配置文件后的各项处理过程,即Spring 容器启动是所执行的各项操作
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
// 父容器
super(parent);
// 设置配置文件
setConfigLocations(configLocations);
if (refresh) {
// 初始化容器
refresh();
}
}
refresh() 方法概述
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// 初始化 BeanFactory
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 调用工厂后置处理器
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// 注册Bean 后置处理器
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 初始化消息源(I18n国际化)
// Initialize message source for this context.
initMessageSource();
// 初始化应用上下文事件广播器
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 初始化其他特殊的 bean ,由子类实现
// Initialize other special beans in specific context subclasses.
onRefresh();
// 注册事件监听器
// Check for listener beans and register them.
registerListeners();
// 初始化所有单实例的Bean,使用懒加载模式的 Bean 除外
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 完成刷新并发布容器刷新事件
// Last step: publish corresponding event.
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。
Spring 将配置文件的信息装入 Bean定义注册表(BeanDefinitionRegistry)中,此时 Bean 还未初始化。根据配置文件,实例化 BeanFactory,在 obtainFreshBeanFactory() 方法中 ,首先调用refreshBeanFactory
方法刷新 BeanFactory,然后调用 getBeanFactory
方法获取 BeanFactory,这两个方法都是由具体的子类实现的。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
- 调用工厂后置处理器。
根据反射机制从 BeanDefinitionRegistry 中找出所有实现了 BeanFactoryPostProcessor 接口的 Bean,并调用其postProcessBeanFactory
方法
- 注册Bean 后置处理器
根据反射机制从 BeanDefinitionRegistry 中找出所有实现了 BeanFactoryPostProcessor 接口的 Bean,并将他们注册到容器 Bean 后置处理器的注册表中
- 初始化消息源(I18n国际化):初始化容器的国际化消息资源
- 初始化应用上下文事件广播器
- 初始化其他特殊的 bean 。由子类实现,如
AbstractRefreshableWebApplicationContext
重写该方法初始化ThemeSource
- 注册事件监听器
- 初始化所有单实例的Bean,放入容器的缓存池中。使用懒加载模式的 Bean 除外。
- 完成刷新并发布容器刷新事件
Bean 装配流程
流程图
-
ResourceLoader 加载配置文件信息,并使用 Resource 表示这个配置文件资源
-
BeanDefinitionReader 读取 Resource 所指向的配置文件资源,解析配置文件。配置文件中每一个 解析成一个 BeanDefinition 对象,并保存在 BeanDefinitionRegistry 中
-
容器扫描 BeanDefinitionRegistry 中的 BeanDefinition ,使用个反射机制自动识别出 Bean 的工厂后置处理器(实现 BeanFactoryPostProcessor 接口),然后调用这个后置处理器的
postProcessBeanFactory()
方法,对 BeanDefinitionRegistry 中的 BeanDefinition 进行加工处理。
- 对使用占位符的 元素标签进行解析,得到最终的配置值
- 对 BeanDefinitionRegistry 中的 BeanDefinition 进行扫描,通过反射扎到属性编辑器 Bean (实现了
java.beans.PropertyEditor
接口),并将其注册到容器的编辑器注册表中(PropertyEditorRegistry)
-
Spring 容器从 BeanDefinitionRegistry 中取出加工后的 BeanDefinition,并调用 InstantiationStrategy 进行 Bean 的实例化工作
-
在实例化 Bean 时,Spring 容器使用 BeanWrapper 对 Bean 进行封装。BeanWrapper 提供了很多反射操作Bean的方法,将结合Bean 的 BeanDefinition 和容器中的属性编辑器,完成对 Bean 的属性注入
-
利用容器中的Bean 的后置处理器(实现 BeanPostProcessor 接口)对已经完成属性设置工作的 Bean 进行后续加工,完成 Bean 的装配工作
BeanDefinition:Bean 在容器中的内部表示
- 简单类图
-
BeanDefinition 是 Bean 在容器中的内部表示。RootBeanDefinition 是最常用的实现类。如果有父子,父为 RootBeanDefinition,子为 ChildBeanDefinition;如果没有父的直接使用 RootBeanDefinition 表示
-
Spring 容器将配置文件中的 配置信息转换为容器中的内部的 BeanDefinition 对象,并将这些 BeanDefinition 注册到 BeanDefinitionRegistry 中,后续的操作直接从 BeanDefinitionRegistry 中获取配置信息。
-
创建最终 BeanDefinition 主要是两个步骤:
- 利用 BeanDefinitionReader 读取配置信息的 Resource,xml 解析成 BeanDefinition 对象。这个时候是个半成品,因为还有占位符存在
- 利用 BeanFactoryPostProcessor 后置工厂处理器对半成品的 BeanDefinition 利用加工,生成成品的的 BeanDefinition
InstantiationStrategy:Bean 实例化策略
- 简单类图
-
org.springframework.beans.factory.support.InstantiationStrategy
负责根据 BeanDefinition 对象创建一个 Bean 实例。相当于 new 的功能,不会参与 Bean 的属性设置工作 -
SimpleInstantiationStrategy 是最常用的实例化策略,该策略利用 Bean 实现类的默认构造函数、带参构造函数、工厂方法创建 Bean 的示例
-
CglibSubclassingInstantiationStrategy 扩展了 SimpleInstantiationStrategy,为需要进行方法注入的 Bean 提供支持。利用 CGLib 类库为 Bean 动态生成子类,在子类方法注入逻辑,然后使用这个动态生成的子类创建 Bean 的示例
BeanWrapper:Bean 属性编辑器填充
- 简单类图
-
org.springframework.beans.BeanWrapper
是Spring 中的重要组件类。相当于一个代理器,Spring 委托 BeanWrapper 完成 Bean 属性的填充工作。在Bean 实例化被 InstantiationStrategy 创建出来后,容器将 Bean 实例通过 BeanWrapper 的包装起来。 -
BeanWrapper 继承了 PropertyAccessor、PropertyEditorRegistry 接口。PropertyAccessor定义了各种访问Bean 属性的方法(getPropertyValue()),PropertyEditorRegistry 是属性编辑器的注册表。所以 BeanWrapper 的实现类 BeanWrapperImpl 具有3重身份:
- Bean 包裹器
- 属性访问器
- 属性编辑器注册表
- BeanWrapperImpl 实例内部封装了两类组件,被封装的待处理的Bean,一套用于设置属性的属性编辑器