Spring Bean的生命周期

概述:

Spring的Bean的生命周期指的是Bean从创建到初始化再到销毁的过程,这个过程由IOC容器管理。一个bean的生命周期主要是4个步骤, 实例化,属性注入,初始化,销毁,但是对于一些复杂的bean的创建,Spring会在Bean的生命周期中开放很多的接口,能够让你加载Bean的时候对Bean做一些改变。在Spring中有一些特殊的Bean会介入到其他Bean的声明周期当中去,所以一个普通的Bean的生命周期为:

  1. 实现了BeanFactoryPostProcessor接口的bean,在加载其他的bean的时候,也会调用这个bean的 postProcessBeanFactory方法,可以在这个步骤去对bean中的属性去赋值。设置年龄初始化为18等。
  2. 实现了InstantiationAwareBeanPostProcessor接口的bean,会在实例化bean之前调用 postProcessBeforeInstantiation方法
  3. 然后再对bean进行实例化
  4. 对bean进行属性注入
  5. 对bean进行初始化,在初始化中,包含了以下几个步骤: 1. 实现了BeanFactoryAware接口,会先调用setBeanFactory方法 2. 实现了BeanNameAware接口,会先调用setBeanName方法 3. 实现了BeanPostProcessor接口,会先调用postProcessBeforeInitialization方法 4. 实现了InitializingBean接口,会调用afterPropertiesSet方法 5. 然后在进行aop后置处理,通过实现BeanPostProcessor接口,在postProcessAfterInitialization方法中进行动态代理
  6. 销毁

Spring 中Bean的详细生命周期

  1. Spring容器启动,加载并注册Bean定义。
  2. 对于每个Bean定义,Spring容器会进行实例化。
  3. 实例化后,Spring容器会将依赖注入Bean的属性中。
  4. 如果Bean实现了BeanNameAware、BeanFactoryAware或ApplicationContextAware接口,Spring容器会调用相应的方法传递相关资源。
  5. 如果Bean实现了BeanPostProcessor接口,Spring容器会调用postProcessBeforeInitialization方法。
  6. 如果Bean实现了InitializingBean接口,Spring容器会调用afterPropertiesSet方法。
  7. 如果Bean定义了初始化方法(如通过@PostConstruct注解或init-method属性),Spring容器会调用该方法。
  8. 如果Bean实现了BeanPostProcessor接口,Spring容器会调用postProcessAfterInitialization方法。
  9. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
  10. 当容器关闭时,如果bean实现了DisposableBean接口或定义了销毁方法(如通过@PreDestroy注解或destroy-method属性),Spring容器会调用相应的方法进行销毁。

JavaDoc文档中除了以上接口外,另外的初始化过程涉及的接口

org.springframework.beans.factory.BeanFactory 中的创建过程:

BeanNameAware.setBeanName() 在创建此bean的bean工厂中设置bean的名称,在普通属性设置之后调用,在InitializinngBean.afterPropertiesSet()方法之前调用

BeanClassLoaderAware``.setBeanClassLoader() : 在普通属性设置之后,InitializingBean.afterPropertiesSet()之前调用

BeanFactoryAware**.setBeanFactory()** : 回调提供了自己的bean实例工厂,在普通属性设置之后,在InitializingBean.afterPropertiesSet()或者自定义初始化方法之前调用

EnvironmentAware``.setEnvironment() : 设置environment在组件使用时调用

EmbeddedValueResolverAware``.setEmbeddedValueResolver() : 设置StringValueResolver 用来解决嵌入式的值域问题

ResourceLoaderAware``.setResourceLoader() : 在普通bean对象之后调用,在afterPropertiesSet 或者自定义的init-method 之前调用,在 ApplicationContextAware 之前调用。

ApplicationEventPublisherAware``.setApplicationEventPublisher() : 在普通bean属性之后调用,在初始化调用afterPropertiesSet 或者自定义初始化方法之前调用。在 ApplicationContextAware 之前调用。

MessageSourceAware``.setMessageSource() : 在普通bean属性之后调用,在初始化调用afterPropertiesSet 或者自定义初始化方法之前调用,在 ApplicationContextAware 之前调用。

ApplicationContextAware.setApplicationContext(): 在普通Bean对象生成之后调用,在InitializingBean.afterPropertiesSet之前调用或者用户自定义初始化方法之前。在ResourceLoaderAware.setResourceLoader,ApplicationEventPublisherAware.setApplicationEventPublisher,MessageSourceAware之后调用。

ServletContextAware``.setServletContext() : 运行时设置ServletContext,在普通bean初始化后调用,在InitializingBean.afterPropertiesSet之前调用,在 ApplicationContextAware 之后调用注入:

BeanPostProcessor.postProcessBeforeInitialization() : 将此BeanPostProcessor 应用于给定的新bean实例 在任何bean初始化回调方法(像是InitializingBean.afterPropertiesSet或者自定义的初始化方法)之前调用。这个bean将要准备填充属性的值。返回的bean示例可能被普通对象包装,默认实现返回是一个bean。

BeanPostProcessor.postProcessAfterInitialization() : 将此BeanPostProcessor 应用于给定的新bean实例 在任何bean初始化回调方法(像是InitializingBean.afterPropertiesSet或者自定义的初始化方法)之后调用。这个bean将要准备填充属性的值。返回的bean示例可能被普通对象包装

InitializingBean.afterPropertiesSet(): 被BeanFactory在设置所有bean属性之后调用(并且满足BeanFactory 和 ApplicationContextAware)。 销毁:

DestructionAwareBeanPostProcessor``.postProcessBeforeDestruction() : 在销毁之前将此BeanPostProcessor 应用于给定的bean实例。能够调用自定义回调,像是DisposableBean 的销毁和自定义销毁方法,这个回调仅仅适用于工厂中的单例bean(包括内部bean)

实现了自定义的destory()方法

总结:

简述Spring Bean 的生命周期:

1.实例化、属性赋值、初始化、销毁这 4 个大阶段;

2.初始化的具体操作,有 Aware 接口的依赖注入、BeanPostProcessor 在初始化前后的处理以及 InitializingBean 和 init-method 的初始化操作;

3.销毁的具体操作,有注册相关销毁回调接口,最后通过DisposableBean 和 destory-method 进行销毁

相关推荐
無限進步D1 小时前
Java 运行原理
java·开发语言·入门
難釋懷1 小时前
安装Canal
java
是苏浙1 小时前
JDK17新增特性
java·开发语言
不光头强2 小时前
spring cloud知识总结
后端·spring·spring cloud
Mike117.2 小时前
GBase 8a 日期边界写法和时间窗口取数偏差
数据库
SPC的存折3 小时前
1、Redis数据库基础
linux·运维·服务器·数据库·redis·缓存
阿里加多5 小时前
第 4 章:Go 线程模型——GMP 深度解析
java·开发语言·后端·golang
likerhood5 小时前
java中`==`和`.equals()`区别
java·开发语言·python
小小李程序员5 小时前
Langchain4j工具调用获取不到ThreadLocal
java·后端·ai
zs宝来了6 小时前
AQS详解
java·开发语言·jvm