Spring 的核心是 IoC 容器悴能,了解 Bean 的生命周期非常重要蛇券,這對 Spring 在項目中的應(yīng)用和擴展都很有幫助崖疤。
一仰冠、生命周期
Bean 的生命周期主要為實例化、屬性填充轻腺、初始化和銷毀 4 個階段乐疆,加上類加載和使用階段,整個流程如下:
二贬养、Bean 的擴展
Spring 在每個階段都提供了擴展點挤土,擴展點可以分為兩類:
- 專用擴展點:用于單個 Bean 的擴展,定義 Bean 類時實現(xiàn)接口來擴展功能误算。
- 通用擴展點:用于所有 Bean 的擴展仰美,單獨定義類實現(xiàn)接口來擴展功能。
1. 專用擴展點
Aware
接口
Aware
接口可以在屬性填充的時候注入 Bean 信息或上下文等信息儿礼。
例如可以通過實現(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 初始化時添加自定義邏輯蜘犁,可以實現(xiàn) InitializingBean
接口翰苫。
如果要在 Bean 銷毀時添加自定義邏輯,可以實現(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
}
}
除了上面兩個回調(diào)接口奏窑,也可以在注冊 Bean 的時候指定自定義初始化和銷毀方法。
@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();
}
}
對應(yīng) XML 配置 <bean>
標簽的 init-method
和 destroy-method
屬性。
還可以使用 JDK 的 @PostConstruct
和 @PreDestroy
注解來指定初始化方法和銷毀方法鹰晨。
public class OneBeanExample {
@PostConstruct
public void init() {
// do some initialization work
}
@PreDestroy
public void destroy() {
// do some destruction work
}
}
前面提供的三種方式都可以定義 Bean 初始化和銷毀時執(zhí)行的方法墨叛。
InitializingBean
和DisposableBean
接口會和 Spring 強耦合。
當(dāng)項目中沒有依賴 Spring 時模蜡,推薦使用第二種或第三種方式漠趁。
2. 通用擴展點
通用擴展點對所有 Bean 有效,需要定義單獨的類來實現(xiàn)忍疾,主要有三個接口:
-
BeanPostProcessor
接口 -
InstantiationAwareBeanPostProcessor
接口 -
DestructionAwareBeanPostProcessor
接口
BeanPostProcessor
接口
實現(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
接口
實現(xiàn)該接口可以在 Bean 實例化前后添加自定義邏輯。
@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
接口
實現(xiàn)該接口可以在 Bean 銷毀前添加自定義邏輯卤妒。
@Component
public class BeanDestroyProcessor implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
// before destruction work
}
}
3. 生命周期擴展點示例
Bean 生命周期的 4 個階段都支持擴展甥绿,每個階段都可以添加自定義邏輯。
3.1 實例化
Spring 容器在這步實例化 Bean 對象则披。
實現(xiàn) InstantiationAwareBeanPostProcessor
接口的兩個擴展方法共缕,在實例化前后添加擴展。
3.2 屬性填充
Spring 容器在這步填充屬性士复,例如通過 Setter 方法注入依賴图谷。
屬性填充后通過 Aware
接口擴展來注入 Bean 信息或上下文等信息。
3.2 初始化
Spring 容器在這步初始化 Bean。
實現(xiàn) BeanPostProcessor
接口的兩個擴展方法蜓萄,在初始化前后添加擴展隅茎。
在初始化階段,前面講到三種方式來指定初始化方法嫉沽,一般情況下使用一種就行。
如果同時使用三種俏竞,三種方式指定的方法相同绸硕,該方法只執(zhí)行一次,當(dāng)三種方式指定的方法不同魂毁,按圖中順序執(zhí)行玻佩。
3.4 銷毀
Spring 容器在這步銷毀 Bean,可以釋放外部資源席楚。
實現(xiàn) DestructionAwareBeanPostProcessor
接口的擴展方法咬崔,可以在銷毀前添加擴展。
在銷毀階段烦秩,前面講到三種方式來指定銷毀方法垮斯,一般情況下使用一種就行。
如果同時使用三種只祠,三種方式指定的方法相同兜蠕,該方法只執(zhí)行一次,當(dāng)三種方式指定的方法不同抛寝,按圖中順序執(zhí)行熊杨。
4. 生命周期擴展點順序
Bean 的生命周期中,通用擴展點和專用擴展點盗舰,以及它們對應(yīng)的方法晶府,執(zhí)行順序如下圖:
三、附錄
1. 配置屬性
屬性 | 描述 |
---|---|
<bean> 的init-method 屬性 |
基于 XML 配置容器中钻趋,指定自定義初始化方法 |
<bean> 的destroy-method 屬性 |
基于 XML 配置容器中川陆,指定自定義銷毀方法 |
2. 常用注解
注解 | 描述 |
---|---|
@Bean 的initMethod 屬性 |
基于 Java 配置容器中,指定自定義初始化方法 |
@Bean 的destroyMethod 屬性 |
基于 Java 配置容器中爷绘,指定自定義銷毀方法 |
@PostConstruct |
使用 JDK 注解指定初始化執(zhí)行的方法 |
@PreDestroy |
使用 JDK 注解指定銷毀執(zhí)行的方法 |
3. 示例代碼
Gitee 倉庫:https://gitee.com/code_artist/spring
項目模塊:spring-ioc
示例路徑:cn.codeartist.spring.bean.life
最新文章關(guān)注 CodeArtist 碼匠公眾號书劝。