Spring Bean的生命周期

6 篇文章 0 订阅
6 篇文章 0 订阅

前言

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 Spring已经载入 已得到配置文件里面的Bean/扫包Bean/其它来源Bean 实例化BeanFactoryPostProcessor实现类(注意每次实例化都是一次Spring Bean的生命最周期) 实例化BeanDefinitionRegistryPostProcessor实现类 执行BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 执行BeanFactoryPostProcessor#postProcessBeanFactory 实例化BeanPostProcessor实现类 配置国际化、增加观察者、添加ThemeSource等 实例化剩余的类(non-lazy-init) 开启Spring生命周期、准备事件推送 等待应用程序执行逻辑 销毁并执行注册了销毁方法等的类的方法 Spring生命周期结束

如上

Spring Bean生命周期 之 初始化

Spring Bean生命周期初始化 如下图所示(只介绍单例、只介绍用户相关):
其中InstantiationAwareBeanPostProcessor是BeanPostProcessor子类 6
BeanPostProcessor的执行顺序可见源码7

如下图
可以直接看UML图8

改版

如上

解析:

  • Spring的初始化离不开Spring Bean的初始化。
  • 每个Spring托管的Bean都必须经历Spring Bean初始化这个流程, BeanFactoryPostProcessor也不例外
    • 在初始化BeanFactoryPostProcessor之前预先初始化了数个BeanPostProcessor
    • 自定义的BeanPostProcessor之所以没有被执行是因为那个时候它们都还没有被初始化
  • BeanPostProcessor 相当于是一个Spring的拓展功能,用户可以通过它对Bean做定制化处理
  • Spring的@Value@Resource等也是通过BeanPostProcessor注入的,也是在Bean生命周期的’初始化’中注入的
  • BeanPostProcessor#postProcessAfterInitialization执行完毕之后Bean的初始化流程就已经完毕,就可以开始执行业务逻辑了。
  • 用户的拓展性
    • 用户希望对Bean做侵入性修改,可以实现BeanPostProcessor或者其子类
    • 用户希望在Bean载入前自定义自己的用户数据,比如配置载入,可以实现BeanFactoryPostProcessor或者其子类
    • 用户希望对Spring Context做到感知,可以实现Aware接口
      • ApplicationContextAware会注入给你当前ApplicationContext
      • BeanFactoryAware会注入给你当前BeanFactory
      • BeanClassLoaderAware会注入给你加载当前系统Bean的ClassLoader
    • 用户希望在属性注入后做一些用户类的初始化操作,可以实现InitializingBean接口
  • Spring Bean初始化生命周期中还有很多其余的操作, 但是大部分都是系统相关的,用户无感知,因此没有做介绍。

附加:Spring事务实现原理

Spring IOC 控制逻辑

在这里插入图片描述

Spring 代理/事务实现流程图

在这里插入图片描述

Spring 事务实现小逻辑

在这里插入图片描述
其中, 类拦截器(各个代理组件)是循环嵌套的, 比如处理异常的, 和处理事务的, 两者是循环嵌套, 且相互兼容的。
在这里插入图片描述


附录

附录一 BeanFactoryPostProcessor UML

BeanFactoryPostProcessor的UML图

BeanDefinitionReg BeanFactoryP 其它子类 PriorityOr dered.class 由上自下依 次 初始化 Ordered.class 非如上两个 类的其余子类 一般情况下只有类 ConfigurationClassPostProcessor 它来初始化Bean的配置类,比如 @ComponentScan,@Bean等等 起到xml配置的一个补充 如果使用了Mybatis,还会有 MapperScannerConfigurer 首先还是初始化 PriorityOrdered实现 例:PropertySourcesPlaceholderConfigurer PriorityOr dered.class 其次初始化 Ordered实现 Ordered.class 其余实现 最后则是BeanFac toryPostPro cessor的剩余实现 BeanDefinitionReg BeanFactoryP 其它子类

附录二 Spring Context UML

Spring Context 的UML图

ServletListener SpringContext SpringInit SpringIOC Java的 Servlet技术 创建 WebApplicationContext spring.xml 依赖Xml 扫包并载入Bean 逐级初始化 SpringBean 应用程序生命周期 ServletListener SpringContext SpringInit SpringIOC

附录三 BeanPostProcessor UML

BeanPostProcessor 的UML图

InstantiationAwar BeanPostProcessor 一个子类,优先级高 于 BeanPos tProcessor 被执行方法 postProcessBefo reInstantiation 被执行方法 postProcessAft erInstantiation 被执行方法 postProcessP ropertyValues 被执行方法postPro cessBeforeIn itialization 如果Bean实现了Initia lizingBean 执行af terPropertiesSet 被执行方法postPr ocessAfterI nitialization InstantiationAwar BeanPostProcessor

附录四 Spring Bean初始化 UML

Spring Bean初始化的UML图

Created with Raphaël 2.2.0 一个Spring Bean(已有配置文件里面的Bean/扫包Bean/其它来源Bean) 未配备自定义Bean初始化 获取这个Bean的Class(往往已经被完成,没完成则通过Class.forName创建) 给这个Class创建一个对象(通过寻找构造器) 依次执行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 依次执行InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 依次执行InstantiationAwareBeanPostProcessor#postProcessPropertyValues 依次执行BeanPostProcessor#postProcessBeforeInitialization 执行Bean自身InitializingBean#afterPropertiesSet 执行Bean自身<init-method /> 依次执行BeanPostProcessor#postProcessAfterInitialization SpringBean初始化结束 依次执行InstantiationAwareBeanPostProcessor#InstantiationAwareBeanPostProcessor 结果为空? 得到自代理的Bean 结果为空? 依次执行BeanPostProcessor#postProcessAfterInstantiation yes no yes no yes no

附录五 Autowire/Resource/Value等注解

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

用于处理Javax所提供的规范,包括:

  • 注入:WebServiceRefEJBResource 等。
  • 起始、结束方法:@PostConstruct@PreDestroy
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

用于处理Spring定义的注入规范,如:

  • 配置、Bean注入:@Autowired@Value@Inject
  • 同时支持Javax定义的注入优先级:@Priority, Spring定义的@Primary(比Priority高优)

注解

InstantiationAwareBeanPostProcessor的方法执行见AbstractAutowireCapableBeanFactory


  1. Spring Context 的UML图见附录二 ↩︎

  2. BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的一个子接口;PriorityOrdered.classOrdered.class是接口类。 ↩︎

  3. BeanFactoryPostProcessor的UML图见附录一 ↩︎

  4. BeanPostProcessorBeanFactoryPostProcessor的初始化方式不一样,它在初始化的时候并不会执行接口里面的方法,只是简单的初始化这个类。BeanPostProcessor的执行是针对所有Spring Bean而言的,一些自定义BeanPostProcessor对BeanFactoryPostProcessor无效是因为那时还没被初始化。 ↩︎

  5. BeanPostProcessor的UML图见附录三 ↩︎

  6. ↩︎
  7. 见图(AbstractAutowireCapableBeanFactory)
    执行顺序 ↩︎

  8. Spring Bean 初始化的UML图见附录四。 ↩︎

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值