Spring之Bean的生命週期

二、生命週期方法說明
介面 | 方法 | 說明 |
---|---|---|
BeanFactoryPostProcessor | postProcessBeanFactory | 在Bean物件例項化之前執行, 通過beanFactory可以獲取bean的定義資訊, 並可以修改bean的定義資訊。這點是和BeanPostProcessor最大區別 |
BeanPostProcessor | postProcessBeforeInitialization | 例項化、依賴注入完畢,在呼叫顯示的初始化之前完成一些定製的初始化任務 |
postProcessAfterInitialization | 例項化、依賴注入、初始化完畢時執行 | |
InstantiationAwareBeanPostProcessor | postProcessBeforeInstantiation | 在方法例項化之前執行,返回結果為null正常執行,返回結果如果不為null則會跳過相關方法而進入初始化完成後的流程 |
postProcessAfterInstantiation | 在方法例項化之後執行,返回結果true才會執行postProcessPropertyValues方法 | |
postProcessPropertyValues | 可以用來修改Bean中屬性的內容 | |
InitializingBean | afterPropertiesSet | 初始化的方法 |
DisposableBean | destroy | 容器銷燬前的回撥方法 |
Aware | setXXX | 感知對應Spring容器的內容 |
@PostConstruct | 標註在方法頭部,表示初始化的方法 | |
@PreDestroy | 標註在方法頭部,表示銷燬前回調的方法 | |
init-method屬性 | 指定初始化的方法 | |
destory-method屬性 | 指定銷燬前的回撥方法 |
三、演示
1.BeanFactoryPostProcessor介面
該介面中的方法是最先執行的。在Bean例項化之前執行
/** * 自定義BeanFactoryPostProcessor * * @author dengp * */ public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { /** * 本方法在Bean物件例項化之前執行, * 通過beanFactory可以獲取bean的定義資訊, * 並可以修改bean的定義資訊。這點是和BeanPostProcessor最大區別 */ @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("****** BeanFactoryPostProcessor 開始執行了"); /*String[] names = beanFactory.getBeanDefinitionNames(); for (String name : names) { if("user".equals(name)){ BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name); MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); // MutablePropertyValues如果設定了相關屬性,可以修改,如果沒有設定則可以新增相關屬性資訊 if(propertyValues.contains("name")){ propertyValues.addPropertyValue("name", "bobo"); System.out.println("修改了屬性資訊"); } } }*/ System.out.println("******* BeanFactoryPostProcessor 執行結束了"); } } 複製程式碼
2.BeanPostProcessor介面
該介面中定義了兩個方法,分別在Bean物件例項化及裝配後在初始化的前後執行
/** * 自定義BeanPostProcessor實現類 * BeanPostProcessor介面的作用是: * 我們可以通過該介面中的方法在bean例項化、配置以及其他初始化方法前後新增一些我們自己的邏輯 * @author dengp * */ public class MyBeanPostProcessor implements BeanPostProcessor{ /** * 例項化、依賴注入完畢,在呼叫顯示的初始化之前完成一些定製的初始化任務 * 注意:方法返回值不能為null * 如果返回null那麼在後續初始化方法將報空指標異常或者通過getBean()方法獲取不到bena例項物件 * 因為後置處理器從Spring IoC容器中取出bean例項物件沒有再次放回IoC容器中 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if("user".equals(beanName)){ System.out.println(">>後置處理器 before方法:"+bean+"\t"+beanName); } // 可以根據beanName不同執行不同的處理操作 return bean; } /** * 例項化、依賴注入、初始化完畢時執行 * 注意:方法返回值不能為null * 如果返回null那麼在後續初始化方法將報空指標異常或者通過getBean()方法獲取不到bena例項物件 * 因為後置處理器從Spring IoC容器中取出bean例項物件沒有再次放回IoC容器中 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if("user".equals(beanName)){ System.out.println("<<後置處理器after方法:"+bean+"\t"+beanName); } // 可以根據beanName不同執行不同的處理操作 return bean; } } 複製程式碼
3.InstantiationAwareBeanPostProcessor介面
該介面是BeanPostProcessor介面的子介面,所以該介面肯定具有BeanPostProcessor介面的功能,同時又定義了三個自己的介面,這三個介面是在Bean例項化前後執行的方法。
/** * 自定義處理器 * @author dengp * */ public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor{ /** * BeanPostProcessor介面中的方法 * 在Bean的自定義初始化方法之前執行 * Bean物件已經存在了 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub if("user".equals(beanName)){ System.out.println("【---InstantiationAwareBeanPostProcessor---】 postProcessBeforeInitialization"); } return bean; } /** * BeanPostProcessor介面中的方法 * 在Bean的自定義初始化方法執行完成之後執行 * Bean物件已經存在了 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if("user".equals(beanName)){ System.out.println("【--InstantiationAwareBeanPostProcessor----】 postProcessAfterInitialization"); } return bean; } /** * InstantiationAwareBeanPostProcessor中自定義的方法 * 在方法例項化之前執行Bean物件還沒有 */ @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if("user".equals(beanName)){ System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessBeforeInstantiation"); } return null; } /** * InstantiationAwareBeanPostProcessor中自定義的方法 * 在方法例項化之後執行Bean物件已經創建出來了 */ @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if("user".equals(beanName)){ System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessAfterInstantiation"); } return true; } /** * InstantiationAwareBeanPostProcessor中自定義的方法 * 可以用來修改Bean中屬性的內容 */ @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { if("user".equals(beanName)){ System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessPropertyValues--->"); } return pvs; } } 複製程式碼
4.BeanNameAware,BeanFactoryAware等Aware介面
Aware介面是用來讓物件感知當前的IOC環境
5.InitializingBean,DisposableBean介面
這兩個介面是Bean初始化及銷燬回撥的方法。
6.@PostConstruct和@PreDestroy註解
package com.dpb.pojo; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; /** * 實現InitializingBean和DisposableBean介面 * @author dengp * */ public class User implements InitializingBean,DisposableBean,BeanNameAware,BeanFactoryAware{ private int id; private String name; //感知本物件在Spring容器中的id屬性 private String beanName; // 感知本物件所屬的BeanFactory物件 private BeanFactory factory; public User(){ System.out.println("構造方法被執行了...User 被例項化"); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { System.out.println("《注入屬性》注入name屬性"+name); this.name = name; } public String getBeanName() { return beanName; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", beanName=" + beanName + "]"; } /** * bean物件銷燬前的回撥方法 */ @Override public void destroy() throws Exception { // TODO Auto-generated method stub System.out.println("《DisposableBean介面》destory ...."); } /** * 初始化的方法 */ @Override public void afterPropertiesSet() throws Exception { System.out.println("初始化:《InitializingBean介面》afterPropertiesSet...."); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { // TODO Auto-generated method stub System.out.println("【BeanFactoryAware介面】setBeanFactory"); this.factory = beanFactory; } @Override public void setBeanName(String name) { System.out.println("【BeanNameWare介面】setBeanName"); this.beanName = name; } public BeanFactory getFactory() { return factory; } /** * 也是個初始化的方法 */ @PostConstruct public void postConstruct(){ System.out.println("初始化:【@PostConstruct】執行了..."); } /** * 銷燬前的回撥方法 */ @PreDestroy public void preDestory(){ System.out.println("【@preDestory】執行了..."); } /** * 初始化的方法 * 通過bean標籤中的 init-method屬性指定 */ public void start(){ System.out.println("初始化:【init-method】方法執行了...."); } /** * 銷燬前的回撥方法 * 通過bean標籤中的 destory-method屬性指定 */ public void stop(){ System.out.println("【destory-method】方法執行了...."); } } 複製程式碼
7.init-method,destroy-method
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <context:annotation-config/> <bean class="com.dpb.pojo.User" id="user" init-method="start" destroy-method="stop" > <property name="name" value="波波烤鴨"></property> </bean> <!-- 註冊後置處理器 --> <bean class="com.dpb.processor.MyBeanPostProcessor"/> <!-- 註冊 InstantiationAwareBeanPostProcessor --> <bean class="com.dpb.processor.MyInstantiationAwareBeanPostProcessor"></bean> <!-- 註冊 BeanFactoryPostProcessor物件--> <bean class="com.dpb.factoryprocessor.MyBeanFactoryPostProcessor"/> </beans> 複製程式碼
8.測試
@Test public void test1() { System.out.println("Spring容器開始載入...."); ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = ac.getBean(User.class); System.out.println("---------------"+user); ac.registerShutdownHook(); System.out.println("Spring容器解除安裝完成...."); } 複製程式碼
輸出結果
Spring容器開始載入.... 三月 04, 2019 11:14:38 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 資訊: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@707f7052: startup date [Mon Mar 04 23:14:38 CST 2019]; root of context hierarchy 三月 04, 2019 11:14:39 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 資訊: Loading XML bean definitions from class path resource [applicationContext.xml] ****** BeanFactoryPostProcessor 開始執行了 ******* BeanFactoryPostProcessor 執行結束了 【--InstantiationAwareBeanPostProcessor----】postProcessBeforeInstantiation 構造方法被執行了...User 被例項化 【--InstantiationAwareBeanPostProcessor----】postProcessAfterInstantiation 【--InstantiationAwareBeanPostProcessor----】postProcessPropertyValues---> 《注入屬性》注入name屬性波波烤鴨 【BeanNameWare介面】setBeanName 【BeanFactoryAware介面】setBeanFactory >>後置處理器 before方法:User [id=0, name=波波烤鴨, beanName=user]user 【---InstantiationAwareBeanPostProcessor---】 postProcessBeforeInitialization 初始化:【@PostConstruct】執行了... 初始化:《InitializingBean介面》afterPropertiesSet.... 初始化:【init-method】方法執行了.... <<後置處理器after方法:User [id=0, name=波波烤鴨, beanName=user]user 【--InstantiationAwareBeanPostProcessor----】 postProcessAfterInitialization ---------------User [id=0, name=波波烤鴨, beanName=user] Spring容器解除安裝完成.... 三月 04, 2019 11:14:39 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 資訊: Closing org.springframework.context.support.ClassPathXmlApplicationContext@707f7052: startup date [Mon Mar 04 23:14:38 CST 2019]; root of context hierarchy 【@preDestory】執行了... 《DisposableBean介面》destroy .... 【destory-method】方法執行了.... 複製程式碼