什么是 Spring Bean 的生命周期

对于普通的 Java 对象,当 new 的时候创建对象,然后该对象就能够使用了。一旦该对象不再被使用,则由 Java 自动进行垃圾回收。

而 Spring 中的对象是 bean,bean 和普通的 Java 对象没啥大的区别,只不过 Spring 不再自己去 new 对象了,而是由 IoC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IoC 容器要即可。IoC 其实就是解决对象之间的耦合问题,Spring Bean 的生命周期完全由容器控制。

Bean的生命周期

Spring bean的生命周期阶段是:

bean定义

bean注册

实列化

依赖注入

初始化

销毁

  • 1.bean定义:就是从xml或注解定位资源加载读取bean的元信息并定义成一个BeanDefinition对象
  • 2.bean注册:将BeanDefinition对象根据相应的规则放到缓存池map中
  • 3.实例化:根据BeanDefinition实例化真正的bean,即是调用构造函数
  • 4.依赖注入:属性赋值调用setter方法,即是依赖注入(DI)
  • 5.初始化: 初始化是用户能自定义扩展的阶段
  • 6.销毁: 销毁是用户能自定义扩展的阶段

注:其他都是在这阶段前后的扩展点

Spring角度查看bean的定义与注册

refresh()

public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// 准备Bean初始化相关的环境信息,其内部提供了一个空实现的initPropertySources()方法用于提供给用户一个更改相关环境信息的机会this.prepareRefresh();// 创建BeanFactory实例,并且注册相关的bean信息ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();// 注册Aware和Processor实例,并且注册了后续处理请求所需的一些Editor信息this.prepareBeanFactory(beanFactory);try {// 提供的一个空方法,用于供给子类对已经生成的BeanFactory的一些信息进行定制this.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// 调用BeanFactoryPostProcessor及其子接口的相关方法,这些接口提供了一个入口,提供给了调用方一个修改已经生成的BeanDefinition的入口this.invokeBeanFactoryPostProcessors(beanFactory);// 对BeanPostProcessor进行注册this.registerBeanPostProcessors(beanFactory);beanPostProcess.end();// 初始化国际化所需的bean信息this.initMessageSource();// 初始化事件广播器的bean信息this.initApplicationEventMulticaster();// 提供的一个空方法,供给子类用于提供自定义的bean信息,或者修改已有的bean信息this.onRefresh();// 注册事件监听器this.registerListeners();// 对已经注册的非延迟(配置文件指定)bean的实例化this.finishBeanFactoryInitialization(beanFactory);// 清除缓存的资源信息,初始化一些声明周期相关的bean,并且发布Context已被初始化的事件this.finishRefresh();} catch (BeansException var10) {if (this.logger.isWarnEnabled()) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);}// 发生异常则销毁已经生成的beanthis.destroyBeans();// 重置refresh字段信息this.cancelRefresh(var10);throw var10;} finally {// 初始化一些缓存信息this.resetCommonCaches();contextRefresh.end();}}
}

SpringBoot角度查看bean定义和注册

1. 自动加载配置类

2. bean定义和注册

注:springboot只是比spring多了自动配置相关流程,在spring上做了一层逻辑封装。

实例化,依赖注入,初始化

AbstractAutowireCapableBeanFactory为AutowireCapableBeanFactory接口的一个实现类,其中AbstractAutowireCapableBeanFactory实现类的一个方法doCreateBean()

//位置:AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {// 实例化阶段instanceWrapper = this.createBeanInstance(beanName, mbd, args);}...Object exposedObject = bean;try {// 依赖注入,属性赋值阶段this.populateBean(beanName, mbd, instanceWrapper);// 初始化阶段exposedObject = this.initializeBean(beanName, exposedObject, mbd);} catch (Throwable var18) {...}...
}

可以发现,分别调用三种方法:

  1. createBeanInstance() -> 实例化
  2. populateBean() -> 依赖注入
  3. initializeBean() -> 初始化

销毁

销毁阶段是在容器关闭时调用的,在ConfigurableApplicationContext#close()

至于xxxAware,BeanPostProcessor,BeanFactoryPostProcessor等类,只不过是对主流程的一系列扩展点而已。

Bean的生命周期的扩展点

Spring Bean 的生命周期的扩展点很多,这里不可能全部列出来,只说核心的扩展点。这也就是为什么 Spring 的扩展性很好的原因,开了很多的口子,尽可能让某个功能高内聚松耦合,用户需要哪个功能就用哪个,而不是直接来一个大而全的东西。

Bean级别

这些接口的实现类是基于 Bean 的,只要实现了这些接口的Bean才起作用

  • BeanNameAware
  • BeanFactoryAware
  • ApplicationContextAware
  • InitializingBean
  • DisposableBean

还要很多的xxxAware,这些不常用,下面生命周期测试就不加上,如:

  • BeanClassLoaderAware
  • EnvironmentAware
  • EmbeddedValueResolverAware
  • ResourceLoaderAware
  • ApplicationEventPublisherAware
  • MessageSourceAware
  • ServletContextAware

容器级别

这些接口的实现类是独立于 Bean 的,并且会注册到 Spring 容器中。一般称它们的实现类为后置处理器。

在 Spring 容器创建任何 Bean 的时候,这些后置处理器都会发生作用

  • BeanPostProcessor
  • InstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor 是继承了 BeanPostProcessor)
  • 工厂后处理器接口也是容器级的。在应用上下文装配配置文件之后立即调用:
    • AspectJWeavingEnabler
    • ConfigurationClassPostProcessor
    • CustomAutowireConfigurer

常用接口

InstantiationAwareBeanPostProcessor

  • 该类是 BeanPostProcessor 的子接口,常用的有如下三个方法:

    • postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用
    • postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、设置属性前调用
    • postProcessAfterInstantiation(Class beanClass, String beanName):在bean实例化之后调用

BeanNameAware

  • BeanNameAware接口是为了让自身Bean能够感知到,只有一个方法setBeanName(String name),获取到自身在Spring容器中的id或name属性。

BeanFactoryAware

  • 该接口只有一个方法setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory,可以对工厂中的所有bean进行扩展。

ApplicationContextAware

  • 该接口只有一个方法setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext,可以对整个容器进行扩展。
  • 注:有时候并不会调用该接口,这要根据你的IOC容器来决定:Spring IOC容器最低要求是实现BeanFactory接口,而不是实现ApplicationContext接口,对于那些没有实现ApplicationContext接口的容器,在生命周期对应的ApplicationContextAware定义的方法也是不会调用的,只要实现了ApplicationContext接口的容器,才会调用。

BeanPostProcessor

  • postProcessBeforeInitialization(Object bean, String beanName):在初始化之前调用此方法,Spring 的 AOP 就是利用它实现的。
  • postProcessAfterInitialization(Object bean, String beanName):在初始化之后调用此方法

InitializingBean

  • 该接口只有一个方法afterPropertiesSet(),在属性注入完成后调用
  • 凡是继承该接口的类,在初始化bean的时候都会执行该方法,可以进行一些属性配置等工作。
  • InitializingBean 对应生命周期的初始化阶段,在源码的invokeInitMethods(beanName, wrappedBean, mbd)方法中调用。

DisposableBean

  • 该接口的作用是在对象销毁时调用,可以做一些资源销毁操作。
  • DisposableBean 类似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了DisposableBean接口的Bean然后调用其destroy()方法

常用注解

@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")

  • @Bean声明一个bean,配合@Configuration注解使用
  • initMethod:声明bean初始化时回调一个方法,该方法需要程序员编写
  • destroyMethod:声明bean销毁时回调一个方法,该方法需要程序员编写

@PostConstruct

  • bean的一个基于注解的初始化方法

@PreDestroy

  • bean的一个基于注解的销毁方法

案例分析

声明一个bean

@Configuration
public class BeanInitAndDestroyConfig {/*** @return 这里没有指定bean名字,默认是方法名*/@Description("测试bean的生命周期")@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")public MyService myServiceBeanName() {//入参数可注入其他依赖return new MyService();}
}
  • 声明一个名为:myServiceBeanName的bean
  • initMethod:bean的初始化方法为:initMethod
  • destroyMethod:bean的销毁方法为:destroyMethod

Animal实现类

  • 这里只是想用来说明 @Qualifier注解能根据bean名称匹配。

我的服务类

  • 即是针对当前bean只调用一次的接口
/*** @Description: bean生命周期测试:这些接口只针对当前bean* @Author: jianweil* @date: 2021/12/8 9:46*/
public class MyService implements Person, BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {private Animal animal = null;private ApplicationContext applicationContext;/***接口规定方法*/@Overridepublic void service() {this.animal.use();}public MyService() {System.out.println("2. [bean实例化]:"+this.getClass().getSimpleName()+"----------构造方法");}/***接口规定方法:注入依赖*/@Override@Autowired@Qualifier("dog")public void setAnimal(Animal animal) {System.out.println("5. [bean属性赋值]:dog----依赖注入");this.animal = animal;}@Overridepublic void setBeanName(String s) {System.out.println("6. 调用【BeanNameAware】--setBeanName:"+s);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("7. 调用【BeanFactoryAware】--setBeanFactory");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;System.out.println("8. 调用【ApplicationContextAware】--setApplicationContext");}/*** 初始化1*/@PostConstructpublic void myInit() {System.out.println("10. [初始化] 注解@PostConstruct自定义初始化方法[myInit]");}/*** 初始化2*/@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("11. [初始化] 接口InitializingBean方法[afterPropertiesSet]");}/*** 初始化3*/public void initMethod() {System.out.println("12. [初始化] 注解@Bean自定义初始化方法[initMethod]");}/*** 销毁1*/@PreDestroypublic void myDestroy() {System.out.println("14. [销毁] 注解@PreDestroy自定义销毁方法[myDestroy]");}/*** 销毁2*/@Overridepublic void destroy() throws Exception {System.out.println("15. [销毁] 接口DisposableBean方法[destroy]");}/*** 销毁3*/public void destroyMethod() {System.out.println("16. [销毁] 注解@Bean自定义销毁方法[destroyMethod]");}
}
  • 这里实现的接口只作用于当前bean(即是上面@bean定义的bean名为myDefineBeanName)生命周期

后置处理器

  • 每个bean生命周期都执行一次
  • 后置处理器是作用于ioc容器中所有bean的生命周期。
/*** @Description: todo* @Author: jianweil* @date: 2021/12/20 17:20*/
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {System.out.println("============================InstantiationAwareBeanPostProcessor-开始======================");System.out.println("1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为"+beanName);}return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {System.out.println("3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为"+beanName);}return true;}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {System.out.println("4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为"+beanName);System.out.println("============================InstantiationAwareBeanPostProcessor-结束======================");}return null;}
}
/*** @Description: 后置bean的初始化器:所有的bean都会拦截执行* @Author: jianweil* @date: 2021/12/8 9:46*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {//这里过滤掉springboot自动配置的bean,只打印我们项目的bean情况if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {System.out.println("9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为" + beanName);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {System.out.println("13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为" + beanName);}return bean;}
}

工厂后置处理器

  • 容器级别,只允许一次
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("0. [容器级别只调用一次] 调用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法");}
}

输出结果和结果解读

  • “//”标记为解读
//容器级别的工厂后置处理器,只在应用上下文装配配置文件之后立即调用1次
0. [容器级别只调用一次] 调用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法//因为我们生命过程只打印("myServiceBeanName".equals(beanName) || "dog".equals(beanName)),所有猫只有构造方法打印了
猫----------构造方法//###############################dog的生命周期###############################################
//后置处理器,容器级别,作用于所有bean
============================InstantiationAwareBeanPostProcessor-开始======================
1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为dog
//狗的实例化
狗----------构造方法
//后置处理器,容器级别,作用于所有bean
3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为dog
//后置处理器,容器级别,作用于所有bean
4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为dog
============================InstantiationAwareBeanPostProcessor-结束======================
//后置处理器,容器级别,作用于所有bean
9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为dog
//后置处理器,容器级别,作用于所有bean
13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为dog
//###############################dog的bean完成,开始myServiceBeanName###############################################//后置处理器,容器级别,作用于所有bean
============================InstantiationAwareBeanPostProcessor-开始======================
1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为myServiceBeanName//实例化
2. [bean实例化]:MyService----------构造方法//后置处理器,容器级别,作用于所有bean
3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为myServiceBeanName
//后置处理器,容器级别,作用于所有bean
4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为myServiceBeanName
============================InstantiationAwareBeanPostProcessor-结束======================//属性赋值,即是依赖注入
5. [bean属性赋值]:dog----依赖注入//bean级别,bean:myServiceBeanName实现了接口BeanNameAware
6. 调用【BeanNameAware】--setBeanName:myServiceBeanName
//bean级别
7. 调用【BeanFactoryAware】--setBeanFactory
//bean级别
8. 调用【ApplicationContextAware】--setApplicationContext//后置处理器,容器级别,作用于所有bean:初始化前处理
9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为myServiceBeanName//初始化
10. [初始化] 注解@PostConstruct自定义初始化方法[myInit]
11. [初始化] 接口InitializingBean方法[afterPropertiesSet]
12. [初始化] 注解@Bean自定义初始化方法[initMethod]//后置处理器,容器级别,作用于所有bean:初始化后处理
13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为myServiceBeanName//容器环境加载完成,这时可以使用所有bean
2021-12-21 11:18:42.994  INFO 18956 --- [           main] c.l.s.SpringbootBeanLifecycleApplication : Started SpringbootBeanLifecycleApplication in 0.719 seconds (JVM running for 1.312)//销毁
14. [销毁] 注解@PreDestroy自定义销毁方法[myDestroy]
15. [销毁] 接口DisposableBean方法[destroy]
16. [销毁] 注解@Bean自定义销毁方法[destroyMethod]Process finished with exit code 0

Bean生命周期图

了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。

Spring的Bean生命周期相关推荐

  1. 【Spring】Bean生命周期源码分析 总结

    [Spring]Bean生命周期源码总结 1.案例验证 定义两个bean A,B 以及实现MyBeanFactoryProcess,MyBeanProcessor,MyInstantiationAwa ...

  2. 【Spring】- Bean生命周期

    2019独角兽企业重金招聘Python工程师标准>>> Spring Bean的生命周期: bean对象实例化 属性注入 beanfactory ApplicationContext ...

  3. Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:撸码识途 jianshu.com/p/70b935f2b3f ...

  4. Spring的Bean生命周期,11 张高清流程图及代码,深度解析

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:https://tech.souyunku.com/?p=1 ...

  5. 浅谈Spring的Bean生命周期和作用域

    学习spring有一段时间了.有的人说Spring的发展就是Java的发展,Spring就是Java的半壁江山,而且AOP思想更是OOP思想的一种扩展和延申.所以今天来浅谈一下spring的生命周期和 ...

  6. Spring配置文件-Bean生命周期配置(init-method方法,destory-method方法)

    1.UserDaoImpl类 public class UserDaoImpl implements UserDao {public UserDaoImpl(){System.out.println( ...

  7. Spring中Bean生命周期、实例化与初始化

    创建Bean的入口:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean. ...

  8. 【Spring】Bean生命周期

    一.背景: 自动注入 UserService 对象, UserService 结构如下 二.创建 Bean 的整体流程: UserService.class ------> 无参的构造方法 -- ...

  9. spring一: 容器以及bean生命周期

    spring框架的几个优点: 1. 轻量级  2. 针对接口编程,解耦合   3. aop编程   4. 方便集成各种优秀框架  5.非侵入式   6.容器 IOC(Inversion of Cont ...

  10. Spring5源码 - 07 Spring Bean 生命周期流程 源码解读02

    文章目录 Pre 通俗流程 finishBeanFactoryInitialization Pre Spring5源码 - 06 Spring Bean 生命周期流程 概述 01 接上文 通俗流程 下 ...

最新文章

  1. oeasy php,oeasy教您玩转linux010106这儿都有啥 ls
  2. 小用lambda函数
  3. linux 文件夹 含义 表示(转)
  4. git schnnel failed to receive handshake, SSLTLS connection failed
  5. cassandra本地连接失败_无法连接到本地Cassandra实例?
  6. 【渝粤题库】陕西师范大学151203 初级会计学作业(笔试题型)
  7. Eclipse中的SVN插件
  8. 中国团队屠榜:COCOMapillary挑战赛包揽全部冠军
  9. Use gradle compile volley framework
  10. 2018.12.18
  11. Lintcode 138. 子数组之和 [Easy]
  12. linux 进程killed_linux下运行Gaussian09进程被killed
  13. java库房仓库管理系统_Java学员作品-仓库管理系统
  14. matlab九节点网络仿真问题,三机九节点电力系统仿真matlab
  15. 谷歌Chrome浏览器不再支持Flash Player的完全解决方案
  16. Kubernets:容器日志收集方案
  17. 12本最具影响力的程序员书籍_书籍书评_酷勤网
  18. crypto-js 加密解密 (TS版本)
  19. C语言中*p++ ,(*p)++ ,*++p ,++*p的区别
  20. vue移动端点击事件延迟_解决Vue 界面在苹果手机上滑动点击事件等卡顿问题_莺语_前端开发者...

热门文章

  1. 1602-LiquidCrystal库
  2. linux 小度 驱动_小度 WiFi 与 Windows 和 Linux
  3. js代码里链接生成二维码
  4. 搭建基于XMPP的即时通讯系统
  5. mac迅雷精简版(迅雷Mac)简约瘦身版
  6. 自用软件系列之:迅雷X ,无广告,纯净版
  7. android studio gradle下载失败处理
  8. 一款功能强大、高颜值、官方出品的Redis可视化工具
  9. landsat 8 卫星 波段介绍 及组合
  10. AD16 pdf打印输出彩色