目錄
Spring Bean的生命週期
Spring容器既Application或者WebApplication會在管理Bean的時候;爲了儘可能的把自己內部的東西機制暴露出來給用戶使用,所以在Bean創建的過程中加了很多機制,通過所謂的"處理器"Processor暴露出來,然後處理器都有自己的順序,我們需要做的就是定義好處理器的邏輯,然後註冊到Sprinhg容器中,Spring就會調用了。下面就是Spring管理Bean的生命週期圖。
下面這張圖描述的更爲詳細。
相關接口的分類
對於上面圖看不懂不要着急因爲你並不認識與生命週期相關的接口。Spring生命週期你可以理解爲四個等級;每個等級中都用有相應的接口,實現其中某個接口或者將實現類注入到Sprng容器,容器就會在相應的時機調用其方法。詳細信息可看下面的一個表格。
- 工廠後處理器接口方法
- 容器級生命週期接口方法
- Bean級生命週期接口方法
- Bean本身方法
分類 | 接口 | 調用時間 |
---|---|---|
工廠後處理器接口 | BeanFactoryPostProcessor | 容器創建完畢,裝配Bean源後立即調用 |
容器後處理器接口 | InstantiationAwareBeanPostProcessor | 分別在調用構造之前,注入屬性之前,實例化完成時調用 |
容器後處理器接口 | BeanPostProcessor | 分別在Bean的初始化方法調用前後執行 |
Bean級後置處理器接口 | BeanNameAware | 注入屬性後調用 |
Bean級後置處理器接口 | BeanFactoryAware | 注入屬性後調用 |
Bean級後置處理器接口 | InitializingBean | 在類本身的初始化方法之前調用其方法(本身也是初始化方法) |
Bean級後置處理器接口 | DiposableBean | 在類本身的銷燬方法執行之前調用其方法(本身也是銷燬方法) |
Bean本身方法 | init方法 | 在注入屬性之後調用初始化方法 |
Bean本身方法 | destroy方法 | 在關閉容器的時候進行銷燬 |
測試SpringBean生命週期的Demo程序
本測試程序來自https://www.cnblogs.com/zrtqsk/p/3735273.html
我在這裏說一下測試程序是如何測試SpringBean
的生命週期的。首先將一個工廠後處理器 BeanFactoryPostProcessor
接口實現注入容器,再將容器後處理器InstantiationAwareBeanPostProcessor
和BeanPostProcessor
注入容器,又在自定義Person
實現了Bean級後處理器BeanNameAware
,BeanFactoryAware
,InitializingBean
和DiposableBean
接口的相關方法,最後就是在自定義的Person類中實現了其本身的init()
方法和destroy()
方法。
- 自定義Person類
public class Person implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean {
private String name;
private String address;
private int phone;
private BeanFactory beanFactory;
private String beanName;
public Person() {
System.out.println("【構造器】調用Person的構造器實例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("【注入屬性】注入屬性name");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("【注入屬性】注入屬性address");
this.address = address;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
System.out.println("【注入屬性】注入屬性phone");
this.phone = phone;
}
@Override
public String toString() {
return "Person [address=" + address + ", name=" + name + ", phone="
+ phone + "]";
}
// 這是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out
.println("【BeanFactoryAware接口】調用BeanFactoryAware.setBeanFactory()");
this.beanFactory = arg0;
}
// 這是BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("【BeanNameAware接口】調用BeanNameAware.setBeanName()");
this.beanName = arg0;
}
// 這是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out
.println("【InitializingBean接口】調用InitializingBean.afterPropertiesSet()");
}
// 這是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】調用DiposibleBean.destory()");
}
// 通過<bean>的init-method屬性指定的初始化方法
public void myInit() {
System.out.println("【init-method】調用<bean>的init-method屬性指定的初始化方法");
}
// 通過<bean>的destroy-method屬性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法");
}
}
- MyBeanPostProcessor (實現容器級別後置處理器)
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("這是BeanPostProcessor實現類構造器!!");
// TODO Auto-generated constructor stub
}
@Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!");
return arg0;
}
@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!");
return arg0;
}
}
- MyInstantiationAwareBeanPostProcessor(實現容器級別後置處理器)
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out
.println("這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!");
}
// 接口方法、實例化Bean之前調用
@Override
public Object postProcessBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法");
return null;
}
// 接口方法、實例化Bean之後調用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法");
return bean;
}
// 接口方法、設置某個屬性時調用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法");
return pvs;
}
}
- MyBeanFactoryPostProcessor (實現容器級別後置處理器)
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("這是BeanFactoryPostProcessor實現類構造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out
.println("BeanFactoryPostProcessor調用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("person");
bd.getPropertyValues().addPropertyValue("phone", "110");
}
}
- 配置Spring的xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="beanPostProcessor" class="com.jimisun.learnspringboot.web.MyBeanPostProcessor">
</bean>
<bean id="instantiationAwareBeanPostProcessor"
class="com.jimisun.learnspringboot.web.MyInstantiationAwareBeanPostProcessor">
</bean>
<bean id="beanFactoryPostProcessor" class="com.jimisun.learnspringboot.web.MyBeanFactoryPostProcessor">
</bean>
<bean id="person" class="com.jimisun.learnspringboot.web.Person" init-method="myInit"
destroy-method="myDestory" scope="singleton" p:name="張三" p:address="廣州"
p:phone="15900000000"/>
</beans>
- Main方法執行測試
public class Main {
public static void main(String[] args) {
System.out.println("現在開始初始化容器");
ApplicationContext factory = new ClassPathXmlApplicationContext("bens.xml");
System.out.println("容器初始化成功");
//得到Preson,並使用
Person person = factory.getBean("person",Person.class);
System.out.println(person);
System.out.println("現在開始關閉容器!");
((ClassPathXmlApplicationContext)factory).registerShutdownHook();
}
}
- 測試結果(我對Main方法執行結果做了格式化,方便參照)
LOGGER測試:現在開始初始化容器
【工廠構造】這是BeanFactoryPostProcessor實現類構造器!!
【工廠方法】BeanFactoryPostProcessor調用postProcessBeanFactory方法
【容器構造】這是BeanPostProcessor實現類構造器!!
【容器構造】這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!
【容器方法】InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法
【類構造】調用Person的構造器實例化
【容器方法】InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法
【類注入屬性】注入屬性address
【類注入屬性】注入屬性name
【類注入屬性】注入屬性phone
【Bean方法:BeanNameAware接口】調用BeanNameAware.setBeanName()
【Bean方法:BeanFactoryAware接口】調用BeanFactoryAware.setBeanFactory()
【容器方法】BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!
【Bean方法:InitializingBean接口】調用InitializingBean.afterPropertiesSet()
【自身方法:init-method】調用<bean>的init-method屬性指定的初始化方法
【容器方法】BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!
【容器方法】InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法
LOGGER測試:容器初始化成功
Person [address=廣州, name=張三, phone=110]
LOGGER測試:現在開始關閉容器!
【Bean級別:DiposibleBean接口】調用DiposibleBean.destory()
【自身方法:destroy-method】調用<bean>的destroy-method屬性指定的初始化方法
將Demo代碼的執行結果與上述表中的執行時機進行對比,看看執行時機是否正確,
小結
理解透徹Spring Bean的生命週期對開發中可以解決比較棘手的問題,對於深入學習Spring Framework框架這是必須要掌握的知識,所以可以多看兩遍。
該教程所屬Java工程師之Spring Framework深度剖析專欄,本系列相關博文目錄 Java工程師之Spring Framework深度剖析專欄