淺談Spring bean 生命周期驗證
一、從源碼注釋看bean生命周期
從JDK源碼上看,BeanFactory實現(xiàn)類需要支持Bean的完整生命周期,完整的初始化方法及其標準順序(格式:接口 方法)為:
1.BeanNameAware setBeanName 設(shè)置bean名稱
2.BeanClassLoaderAware setBeanClassLoader 設(shè)置bean類加載器
3.BeanFactoryAware setBeanFactory 設(shè)置bean工廠
4.EnvironmentAware setEnvironment 設(shè)置環(huán)境:profiles+properties
5.EmbeddedValueResolverAware setEmbeddedValueResolver 設(shè)置嵌入式值解析器
6.ResourceLoaderAware setResourceLoader 設(shè)置資源載入器,只適用于在應(yīng)用程序上下文中運行
7.ApplicationEventPublisherAware setApplicationEventPublisher注入應(yīng)用事件發(fā)布器ApplicationEventPublisher
8.MessageSourceAware setMessageSource 設(shè)置國際化支持
9.ApplicationContextAware setApplicationContext 設(shè)置應(yīng)用上下文
10.ServletContextAware setServletContext 設(shè)置servlet上下文
11.BeanPostProcessors postProcessBeforeInitialization 執(zhí)行bean處理器前置方法
12.InitializingBean afterPropertiesSet 執(zhí)行初始化Bean設(shè)置完屬性后置方法
13.a custom init-method definition 執(zhí)行自定義初始化方法
14.BeanPostProcessors postProcessAfterInitialization 執(zhí)行bean處理器后置方法
銷毀順序:
1.DestructionAwareBeanPostProcessors postProcessBeforeDestruction 銷毀處理器的前置方法
2.DisposableBean destroy Bean銷毀回調(diào)方法
3.a custom destroy-method definition 用戶自定義銷毀方法
核心方法流程圖:

二、測試驗證
2.1分析原理
前面說的17個步驟都可以測試,我們選取其中的8個步驟進行測試如下:
初始化流程:
1.BeanNameAware setBeanName 設(shè)置bean名稱
3.BeanFactoryAware setBeanFactory 設(shè)置bean工廠
11.BeanPostProcessors postProcessBeforeInitialization 執(zhí)行bean處理器前置方法
12.InitializingBean afterPropertiesSet 執(zhí)行初始化Bean設(shè)置完屬性后置方法
13.a custom init-method definition 執(zhí)行自定義初始化方法
14.BeanPostProcessors postProcessAfterInitialization 執(zhí)行bean處理器后置方法
銷毀流程:
2.DisposableBean destroy Bean銷毀回調(diào)方法
3.a custom destroy-method definition 用戶自定義銷毀方法
2.2 代碼清單
1.構(gòu)建一個Person類,實現(xiàn)BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean接口。
package spring.ioc;
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;
public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
private String name;
private String mobile;
public Person() {
super();
System.out.println("[構(gòu)造器] 調(diào)用Person的構(gòu)造器實例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("[屬性注入] name="+name);
this.name = name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
System.out.println("[屬性注入] mobile="+mobile);
this.mobile = mobile;
}
@Override
public void destroy() throws Exception {
System.out.println("[接口DisposableBean.destroy() ]");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("[接口InitializingBean.afterPropertiesSet() ]");
}
@Override
public void setBeanName(String name) {
System.out.println("[接口BeanNameAware.setBeanName() ]");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("[接口BeanFactoryAware.setBeanFactory() ]");
}
public void myInit(){
System.out.println("[init-method]調(diào)用<bean>的init-method屬性指定的初始化方法");
}
public void myDestory() {
System.out.println("[destroy-method]調(diào)用<bean>的destroy-method屬性指定的銷毀方法");
}
}
2.自定義工廠后處理器,復(fù)寫postProcessBeanFactory方法,獲取bean定義后添加屬性mobile=110
package spring.ioc;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/**
*
* @ClassName:MyBeanFactoryPostProcessor
* @Description:自定義工廠后處理器
* @author diandian.zhang
* @date 2017年10月25日下午7:14:09
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("[MyBeanFactoryPostProcessor工廠后處理器]BeanFactoryPostProcessor實現(xiàn)類構(gòu)造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out.println("[MyBeanFactoryPostProcessor工廠后處理器]BeanFactoryPostProcessor.postProcessBeanFactory()獲取bean定義后添加屬性mobile=110");
BeanDefinition bd = arg0.getBeanDefinition("person");
bd.getPropertyValues().addPropertyValue("mobile", "110");
}
}
3.自定義Bean后處理器,復(fù)寫postProcessBeforeInitialization和postProcessAfterInitialization2個方法,分別對應(yīng)初始化前后時的操作。
package spring.ioc;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
*
* @ClassName:MyBeanPostProcessor
* @Description:自定義Bean后處理器
* @author diandian.zhang
* @date 2017年10月25日下午7:03:53
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("這是BeanPostProcessor實現(xiàn)類構(gòu)造器!!");
}
/**
*
* @Description 初始化前,處理器
* @param bean
* @param beanName
* @return
* @throws BeansException
* @author diandian.zhang
* @date 2017年10月25日下午7:07:02
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!beanName="+beanName);
return bean;
}
/**
*
* @Description 初始化后,處理器
* @param bean
* @param beanName
* @return
* @throws BeansException
* @author diandian.zhang
* @date 2017年10月25日下午7:07:07
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!beanName="+beanName);
return bean;//注意,如果返回null,后續(xù)BeanPostProcessor不會再執(zhí)行
}
}
4.自定義實例化bean后處理器適配器,復(fù)寫postProcessBeforeInstantiation、postProcessBeforeInstantiation、postProcessPropertyValues分別對應(yīng)實例化Bean前調(diào)用、實例化Bean后調(diào)用、設(shè)置某個屬性時調(diào)用
注意:InstantiationAwareBeanPostProcessorAdapter ,這里是實例化Instantiation,不是初始化Initialization?。?!
package spring.ioc;
import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
/**
*
* @ClassName:MyInstantiationAwareBeanPostProcessor
* @Description:BeanPostProcessor的子類,增加了更多自定方法
* @author diandian.zhang
* @date 2017年10月25日下午7:09:15
*/
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out.println("這是InstantiationAwareBeanPostProcessorAdapter實現(xiàn)類構(gòu)造器??!");
}
// 接口方法、實例化Bean之前調(diào)用
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass,String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor調(diào)用postProcessBeforeInstantiation方法[實例化Bean之前調(diào)用 ]beanname="+beanName);
return null;
}
// 接口方法、實例化Bean之后調(diào)用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out .println("InstantiationAwareBeanPostProcessor調(diào)用postProcessAfterInitialization方法[實例化Bean之后調(diào)用]beanname="+beanName);
return bean;
}
// 接口方法、設(shè)置某個屬性時調(diào)用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor調(diào)用postProcessPropertyValues方法 pvs="+pvs+",beanName="+beanName);
return pvs;
}
}
5.測試類,使用ClassPathXmlApplicationContext從xml中讀取bean配置文件生成applicationContext容器應(yīng)用上下文,這一步對應(yīng)容器初始化。第二部從應(yīng)用上下文中獲取bean。最后一步注冊一個關(guān)閉鉤子,在容器關(guān)閉時觸發(fā)。
package spring.ioc;
import org.junit.Test; 6 import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;10
import spring.aop.xml.dao.Dao;
/**
*
* @ClassName:IOCTest
* @Description:測試類
* @author diandian.zhang
* @date 2017年10月25日下午4:42:01
*/
public class IOCTest {
@Test
public void iocPersonTest(){
System.out.println("=============容器初始化======start=========");
@SuppressWarnings("resource")
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("simple_spring_bean.xml");//源碼入口
System.out.println("=============容器初始化=======end========");
System.out.println("=============獲取person bean====start=======");
Person person = applicationContext.getBean("person",Person.class);//獲取Bean
System.out.println("=============獲取person bean====end=======,person類名="+person.getClass().getName());
System.out.println("=============注冊關(guān)閉鉤子,關(guān)閉容器(JVM shutdown)時觸發(fā)鉤子!================");
((ClassPathXmlApplicationContext)applicationContext).registerShutdownHook();
}
}
直接運行,結(jié)果如下:
=============容器初始化======start========= log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. [MyBeanFactoryPostProcessor工廠后處理器]BeanFactoryPostProcessor實現(xiàn)類構(gòu)造器?。? [MyBeanFactoryPostProcessor工廠后處理器]BeanFactoryPostProcessor.postProcessBeanFactory()獲取bean定義后添加屬性mobile=110 這是BeanPostProcessor實現(xiàn)類構(gòu)造器??! 這是InstantiationAwareBeanPostProcessorAdapter實現(xiàn)類構(gòu)造器!! InstantiationAwareBeanPostProcessor調(diào)用postProcessBeforeInstantiation方法[實例化Bean之前調(diào)用 ]beanname=person [構(gòu)造器] 調(diào)用Person的構(gòu)造器實例化 InstantiationAwareBeanPostProcessor調(diào)用postProcessPropertyValues方法 pvs=PropertyValues: length=2; bean property 'mobile'; bean property 'name',beanName=person [屬性注入] mobile=110 [屬性注入] name=張三 [接口BeanNameAware.setBeanName() ] [接口BeanFactoryAware.setBeanFactory() ] BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!beanName=person [接口InitializingBean.afterPropertiesSet() ] [init-method]調(diào)用<bean>的init-method屬性指定的初始化方法 BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!beanName=person InstantiationAwareBeanPostProcessor調(diào)用postProcessAfterInitialization方法[實例化Bean之后調(diào)用]beanname=person =============容器初始化=======end======== =============獲取person bean====start======= =============獲取person bean====end=======,person類名=spring.ioc.Person =============注冊關(guān)閉鉤子,關(guān)閉容器(JVM shutdown)時觸發(fā)鉤子!================ [接口DisposableBean.destroy() ] [destroy-method]調(diào)用<bean>的destroy-method屬性指定的銷毀方法
總結(jié)流程:


以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot Session共享實現(xiàn)圖解
這篇文章主要介紹了SpringBoot Session共享實現(xiàn)圖解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-01-01
Spring 實現(xiàn)數(shù)據(jù)庫讀寫分離的示例
現(xiàn)在大型的電子商務(wù)系統(tǒng),在數(shù)據(jù)庫層面大都采用讀寫分離技術(shù),我們通常的做法就是把查詢從主庫中抽取出來,采用多個從庫,使用負載均衡,減輕每個從庫的查詢壓力。2017-01-01
SpringCloud及Nacos服務(wù)注冊IP選擇問題解決方法
這篇文章主要介紹了SpringCloud及Nacos服務(wù)注冊IP選擇問題,為什么注冊的IP和真實IP不符合呢,原因是Nacos客戶端在注冊服務(wù)時會從機器網(wǎng)卡中選擇一個IP來注冊,所以,當(dāng)注冊了的是非真實IP后,另一臺機器調(diào)用時是不可能調(diào)通的,知道問題原因就是解決方法,一起看看吧2024-01-01
java編程實現(xiàn)獲取服務(wù)器IP地址及MAC地址的方法
這篇文章主要介紹了java編程實現(xiàn)獲取機器IP地址及MAC地址的方法,實例分析了Java分別針對單網(wǎng)卡及多網(wǎng)卡的情況下獲取服務(wù)器IP地址與MAC地址的相關(guān)技巧,需要的朋友可以參考下2015-11-11

