文章目录
前言
Spring作为当前Java最流行、最强大的轻量级框架,受到了程序员的热烈欢迎。准确的了解Spring Bean的生命周期是非常必要的。我们通常使用ApplicationContext作为Spring容器。这里,我们讲的也是 ApplicationContext中Bean的生命周期。而实际上BeanFactory也是差不多的,只不过处理器需要手动注册。 – 这段话系摘抄
一直以来都很想总结一份Spring Bean的生命周期序列图来, 趁最近有时间, 画一份。
此处以Web为例
可以直接看UML图1
Spring Bean结构
BeanFactoryPostProcessor
BeanFactoryPostProcessor
是Spring中一个优先级较高的Bean, 它主要负责处理一些系统启动所需的依赖。
下图描述了系统对它的初始化流程,优先级自上而下:2可以直接看UML图3
可以看出, 一般使用到BeanFactoryPostProcessor的有配置文件的加载、mybatis的扫包、以及在代码里面写死的一些扫包路径等。
它们的初始化优先级最高、最先被Spring初始化。
BeanPostProcessor
BeanPostProcessor
是Spring架构设计"开闭原则"中的一环。"依赖注入"便是依赖这个接口实现的。
这个接口有不少子类。比如
InstantiationAwareBeanPostProcessor
子类负责依赖注入(@Resource
、@Value
等)可见 Spring PropertySourcesPlaceholderConfigurer工作原理DestructionAwareBeanPostProcessor
负责处理@PostConstruct
和@PreDestroy
注解。这里只记录了用户相关性比较大的, 框架相关(如
MergedBeanDefinitionPostProcessor
)的不做介绍
优先级自上而下:4
可以直接看UML图5
序列图
Spring生命周期 之 Spring的载入
Spring的载入依赖于web.xml配置。依赖于 Java Servlet 之 Filter
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
一般情况下,还会加上配置文件,即:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
Spring Context基本流程为:
Spring Context的初始化依赖于Java Servlet流程。可参考ServletContext作用功能详解 文章。
- Spring依赖于Servlet Context 创建WebApplicationContext。
- 创建BeanFactory。
- 解析Spring XML填充BeanFactory(
BeanDefinitionParserDelegate
)。 - 完成Spring载入。
Spring对xml标签的解析是通过NamespaceHandler来实现的。需要被Spring识别,则必须将所需文件放在
${CLASSPATH}/META-INF
下。其中
spring.tooling
记录schemas信息,
spring.schemas
记录xsd存放位置
spring.handlers
记录NamespaceHandler类的路径。
例如:
http://www.springframework.org/schema/context
这个schemas使用ContextNamespaceHandler
来代理解析,其下的<context:component-scan base-package="**" />
标签则对应着ComponentScanBeanDefinitionParser
这个解析器。它的作用就是进行全局扫包。
Spring的载入流程,起始于Servlet, 终止与 org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
。
整个流程通过对xml文件的解析实现如:
context:component-scan
扫包功能import
将一个xml拆分成多个xmlbean
定义一个Spring Beandubbo:provider
自定义标签等功能
Spring的生命周期跟Spring Bean的生命周期是不一样的。
Spring生命周期 之 Spring的整体流程
Spring 后续流程在类
AbstractApplicationContext
中。
起始于#postProcessBeanFactory
。
下面有一段源码解析。 这段源码解析里面的大部分功能需要“Spring Bean生命周期”去支持
// 对Web Spring而言, 这儿注册了个BeanPostProcessor.
// 这步很重要, 因为后续的BeanFactoryPostProcessor的实例类需要这个做预处理
postProcessBeanFactory(beanFactory);
// 在此处通过PostProcessorRegistrationDelegate对BeanFactoryPostProcessor进行初始化.
// 在 Spring载入流程中 通过扫包(component-scan)、 自定义标签(<bean />)等方式获取到的BeanFactoryPostProcessor,将会在这儿进行初始化。
// 一般令人喜闻乐见的PropertySourcesPlaceholderConfigurer就是在这儿进行初始化的。它会将配置文件切分成kv形式的Properties。在后续流程中使用。
// BeanFactoryPostProcessor也是Spring Bean, 也遵守与Spring生命周期的规则。
// BeanFactoryPostProcessor不仅被初始化,还被执行了postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(beanFactory);
// 在此处通过PostProcessorRegistrationDelegate对BeanPostProcessor等进行初始化.
// 流程很简单,将BeanPostProcessor加入预备列表. 用于贯穿Spring Bean的生命周期
// TODO 比如包含@Resource、@Value等非配置类注解的Bean, 就会通过BeanPostProcessor对它们进行赋值。
// BeanPostProcessor仅仅被初始化,没有执行它的方法(它本就是给别的类用的)
registerBeanPostProcessors(beanFactory);
// 配置国际化操作(如果有相关bean)
initMessageSource();
// 指定SimpleApplicationEventMulticaster作为系统观察者
// 可见ApplicationEventPublisherAware, ApplicationEvent
initApplicationEventMulticaster();
// 对web而言,这里主要是注册一个ThemeSource。
// 使用jsp的时候会体现出一些页面颜色的变换。
onRefresh();
// 在initApplicationEventMulticaster()中注册了观察者, 在此处为观察者添加被观察者。
// 在这里观察者们就可以接受Context消息了。
registerListeners();
// 这里是对所有剩余Bean(non-lazy-init)的初始化
// 也是Spring初始化的很关键一步。
finishBeanFactoryInitialization(beanFactory);
// 此处开启了Spring的生命周期
// 事件也可以开始被发送
finishRefresh();
见下图。
这张图是对Spring生命周期的部分描述。