Spring Bean的生命周期

前言

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架构设计"开闭原则"中的一环。"依赖注入"便是依赖这个接口实现的。
这个接口有不少子类。比如

  1. InstantiationAwareBeanPostProcessor子类负责依赖注入(@Resource@Value等)可见 Spring PropertySourcesPlaceholderConfigurer工作原理
  2. 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基本流程为:

Created with Raphaël 2.2.0 1.创建WebApplicationContext 2.创建BeanFactory 3.解析Spring配置 (<bean />;<context:component-scan />等) 以填充BeanFactory 4.找到的NamespaceHandler以用于Bean的解析 5.根据NamespaceHandler找到BeanDefinitionParser Parser Bean(例如注册mvn、注册解析配置文件的类) 6.SpringBean载入结束

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拆分成多个xml
  • bean 定义一个Spring Bean
  • dubbo: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生命周期的部分描述。

Created with Raphaël 2.2.0
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值