Spring的Bean生命周期和擴(kuò)展點(diǎn)
????一、生命周期
????二、Bean 的擴(kuò)展????????1. 專用擴(kuò)展點(diǎn)????????2. 通用擴(kuò)展點(diǎn)????????3. 生命周期擴(kuò)展點(diǎn)示例????????????3.1 實(shí)例化????????????3.2 屬性填充????????????3.2 初始化????????????3.4 銷毀????????4. 生命周期擴(kuò)展點(diǎn)順序????三、附錄????????1. 配置屬性????????2. 常用注解????????3. 示例代碼Spring 的核心是 IoC 容器,了解 Bean 的生命周期非常重要,這對(duì) Spring 在項(xiàng)目中的應(yīng)用和擴(kuò)展都很有幫助。
一、生命周期
Bean 的生命周期主要為實(shí)例化、屬性填充、初始化和銷毀 4 個(gè)階段,加上類加載和使用階段,整個(gè)流程如下:

二、Bean 的擴(kuò)展
Spring 在每個(gè)階段都提供了擴(kuò)展點(diǎn),擴(kuò)展點(diǎn)可以分為兩類:
專用擴(kuò)展點(diǎn):用于單個(gè) Bean 的擴(kuò)展,定義 Bean 類時(shí)實(shí)現(xiàn)接口來(lái)擴(kuò)展功能。
通用擴(kuò)展點(diǎn):用于所有 Bean 的擴(kuò)展,單獨(dú)定義類實(shí)現(xiàn)接口來(lái)擴(kuò)展功能。
1. 專用擴(kuò)展點(diǎn)
Aware 接口
Aware 接口可以在屬性填充的時(shí)候注入 Bean 信息或上下文等信息。
例如可以通過(guò)實(shí)現(xiàn) BeanNameAware 接口將當(dāng)前 Bean 的名稱注入到類中。
public?class?OneBeanExample?implements?BeanNameAware?{
????private?String beanName;
????@Override
????public?void?setBeanName(String name)?{
????????this.beanName = name;
????}
}Spring 提供了許多 Aware 的子接口可以使用,常用的有:
| Aware接口 | 注入依賴 |
|---|---|
BeanNameAware | Bean 的名稱 |
BeanFactoryAware | 當(dāng)前上下文的 BeanFactory |
ApplicationContextAware | 當(dāng)前上下文的 ApplicationContext |
ApplicationEventPublisherAware | 當(dāng)前上下文的事件發(fā)布者 ApplicationEventPublisher |
BeanClassLoaderAware | 加載 Bean 類的類加載器 |
InitializingBean 和 DisposableBean 接口
如果要在 Bean 初始化時(shí)添加自定義邏輯,可以實(shí)現(xiàn) InitializingBean 接口。
如果要在 Bean 銷毀時(shí)添加自定義邏輯,可以實(shí)現(xiàn) DisposableBean 接口。
public?class?OneBeanExample?implements?InitializingBean, DisposableBean?{
????@Override
????public?void?afterPropertiesSet()?{
????// do some initialization work
????}
????@Override
????public?void?destroy()?{
????// do some destruction work
????}
}除了上面兩個(gè)回調(diào)接口,也可以在注冊(cè) Bean 的時(shí)候指定自定義初始化和銷毀方法。
@Bean 注解的 initMethod 屬性指定 Bean 初始化方法,destroyMethod 屬性指定 Bean 銷毀方法。
public?class?OneBeanExample?{
????public?void?init()?{
????????// do some initialization work
????}
????public?void?destroy()?{
????????// do some destruction work
????}
}
@Configuration
public?class?AppConfig?{
????@Bean(initMethod = "init", destroyMethod = "destroy")
????public?OneBeanExample oneBeanExample()?{
????????return?new?OneBeanExample();
????}
}對(duì)應(yīng) XML 配置 標(biāo)簽的 init-method 和 destroy-method 屬性。
還可以使用 JDK 的 @PostConstruct 和 @PreDestroy 注解來(lái)指定初始化方法和銷毀方法。
public?class?OneBeanExample?{
????@PostConstruct
????public?void?init()?{
????????// do some initialization work
????}
????@PreDestroy
????public?void?destroy()?{
????????// do some destruction work
????}
}前面提供的三種方式都可以定義 Bean 初始化和銷毀時(shí)執(zhí)行的方法。
InitializingBean和DisposableBean接口會(huì)和 Spring 強(qiáng)耦合。當(dāng)項(xiàng)目中沒(méi)有依賴 Spring 時(shí),推薦使用第二種或第三種方式。
2. 通用擴(kuò)展點(diǎn)
通用擴(kuò)展點(diǎn)對(duì)所有 Bean 有效,需要定義單獨(dú)的類來(lái)實(shí)現(xiàn),主要有三個(gè)接口:
BeanPostProcessor接口InstantiationAwareBeanPostProcessor接口DestructionAwareBeanPostProcessor接口

BeanPostProcessor 接口
實(shí)現(xiàn)該接口可以在 Bean 初始化前后添加自定義邏輯。
@Component
public?class?BeanInitProcessor?implements?BeanPostProcessor?{
????@Override
????public?Object postProcessBeforeInitialization(Object bean, String beanName)?throws?BeansException {
????????// before initialization work
????????return?bean;
????}
????@Override
????public?Object postProcessAfterInitialization(Object bean, String beanName)?throws?BeansException {
????????// after initialization work
????????return?bean;
????}
}InstantiationAwareBeanPostProcessor 接口
實(shí)現(xiàn)該接口可以在 Bean 實(shí)例化前后添加自定義邏輯。
@Component
public?class?BeanInstanceProcessor?implements?InstantiationAwareBeanPostProcessor?{
????@Override
????public?Object postProcessBeforeInstantiation(Class> beanClass, String beanName)?throws?BeansException {
????????// before instantiation work
????????return?null;
????}
????@Override
????public?boolean?postProcessAfterInstantiation(Object bean, String beanName)?throws?BeansException {
????????// after instantiation work
????????return?true;
????}
}DestructionAwareBeanPostProcessor 接口
實(shí)現(xiàn)該接口可以在 Bean 銷毀前添加自定義邏輯。
@Component
public?class?BeanDestroyProcessor?implements?DestructionAwareBeanPostProcessor?{
????@Override
????public?void?postProcessBeforeDestruction(Object bean, String beanName)?throws?BeansException {
????????// before destruction work
????}
}3. 生命周期擴(kuò)展點(diǎn)示例
Bean 生命周期的 4 個(gè)階段都支持?jǐn)U展,每個(gè)階段都可以添加自定義邏輯。
3.1 實(shí)例化
Spring 容器在這步實(shí)例化 Bean 對(duì)象。
實(shí)現(xiàn) InstantiationAwareBeanPostProcessor 接口的兩個(gè)擴(kuò)展方法,在實(shí)例化前后添加擴(kuò)展。

3.2 屬性填充
Spring 容器在這步填充屬性,例如通過(guò) Setter 方法注入依賴。
屬性填充后通過(guò) Aware 接口擴(kuò)展來(lái)注入 Bean 信息或上下文等信息。

3.2 初始化
Spring 容器在這步初始化 Bean。
實(shí)現(xiàn) BeanPostProcessor 接口的兩個(gè)擴(kuò)展方法,在初始化前后添加擴(kuò)展。

在初始化階段,前面講到三種方式來(lái)指定初始化方法,一般情況下使用一種就行。
如果同時(shí)使用三種,三種方式指定的方法相同,該方法只執(zhí)行一次,當(dāng)三種方式指定的方法不同,按圖中順序執(zhí)行。
3.4 銷毀
Spring 容器在這步銷毀 Bean,可以釋放外部資源。
實(shí)現(xiàn) DestructionAwareBeanPostProcessor 接口的擴(kuò)展方法,可以在銷毀前添加擴(kuò)展。

在銷毀階段,前面講到三種方式來(lái)指定銷毀方法,一般情況下使用一種就行。
如果同時(shí)使用三種,三種方式指定的方法相同,該方法只執(zhí)行一次,當(dāng)三種方式指定的方法不同,按圖中順序執(zhí)行。
4. 生命周期擴(kuò)展點(diǎn)順序
Bean 的生命周期中,通用擴(kuò)展點(diǎn)和專用擴(kuò)展點(diǎn),以及它們對(duì)應(yīng)的方法,執(zhí)行順序如下圖:

三、附錄
1. 配置屬性
| 屬性 | 描述 |
|---|---|
的init-method屬性 | 基于 XML 配置容器中,指定自定義初始化方法 |
的destroy-method屬性 | 基于 XML 配置容器中,指定自定義銷毀方法 |
2. 常用注解
| 注解 | 描述 |
|---|---|
@Bean的initMethod屬性 | 基于 Java 配置容器中,指定自定義初始化方法 |
@Bean的destroyMethod屬性 | 基于 Java 配置容器中,指定自定義銷毀方法 |
@PostConstruct | 使用 JDK 注解指定初始化執(zhí)行的方法 |
@PreDestroy | 使用 JDK 注解指定銷毀執(zhí)行的方法 |
3. 示例代碼
Gitee 倉(cāng)庫(kù):
https://gitee.com/code_artist/spring
項(xiàng)目模塊:
spring-ioc
示例路徑:
cn.codeartist.spring.bean.life
