1、簡要說明
1)本文基於spring5.1.7版本,採用ApplicationContext獲取bean對象。
2)BeanFactory和ApplicationContext對於bean後置處理器還有所不同,需要注意,ApplicationContext會自動檢測在配置文件中實現了BeanPostProcessor接口的所有bean,並把它們註冊爲後置處理器,然後在容器創建bean的適當時候調用它,因此部署一個後置處理器同部署其他的bean並沒有什麼區別。而使用BeanFactory實現的時候,bean 後置處理器必須通過代碼顯式地去註冊。
2、Bean的生命週期
2.1、生命週期流程圖
2.2、總體概述
我們知道一個對象的生命週期:創建(實例化-初始化)-使用-銷燬,而在Spring中,Bean對象週期當然遵從這一過程,但是Spring提供了許多對外接口,允許開發者對三個過程(實例化、初始化、銷燬)的前後做一些操作。
這裏就實例化、初始化區別做一個說明,在Spring Bean中,實例化是爲bean對象開闢空間(具體可以理解爲構造函數的調用),初始化則是對屬性的初始化,說的具體點,這裏的屬性初始化應該是屬性的注入(構造函數也可以有屬性的初始化語句,但不屬於這一部分),屬性注入是通過setter方法注入屬性(不管是註解方式還是bean配置property屬性方式,其實質都是通過屬性的setter方法實現的)。
2.3、接口及方法介紹
Bean的完整生命週期經歷了各種方法調用,這些方法可以劃分爲以下幾類:
1)Bean自身的方法:這個包括了Bean本身調用的方法和通過配置文件中的init-method和destroy-method指定的方法
2)Bean級生命週期接口方法:BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這些接口的方法。每個Bean選擇實現,可選擇各自的個性化操作。
3、容器級生命週期接口方法:這個包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個接口實現(前者繼承自後者),一般稱它們的實現類爲“後處理器”。這些接口是每個bean實例化或初始化時候都會調用。
4、工廠後處理器接口方法:這些方法也是容器級別的,但它們是在上下文裝置配置文件之後調用,例如BeanFactoryPostProcessor、 CustomAutowireConfigurer等。
3、具體代碼實現
1)定義一個bean類(CustomBean)
它實現了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這4個接口,同時有2個方法,對應配置文件中的init-method和destroy-method。
/**
* @author xf
* @description 自定義bean
* @date 2019/5/22 11:52
*/
public class CustomBean implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean {
private String name;
private String address;
private BeanFactory beanFactory;
private String beanName;
public CustomBean() {
System.out.println("第6步:【構造器】調用CustomBean的構造器實例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("第9步:【注入屬性】注入屬性name");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("第10步:【注入屬性】注入屬性address");
this.address = address;
}
@Override
public String toString() {
return "CustomBean{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
// 通過spring的xml配置文件<bean>的init-method屬性指定的初始化方法
public void xml_init() {
System.out.println("第16步:【init-method】調用<bean>的init-method屬性指定的初始化方法");
}
// 通過spring的xml配置文件<bean>的destroy-method屬性指定的初始化方法
public void xml_destroy() {
System.out.println("第21步:【destroy-method】調用<bean>的destroy-method屬性指定的銷燬方法");
}
// 這是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out
.println("第12步:【執行BeanFactoryAware接口的setBeanFactory方法】setBeanName後調用");
this.beanFactory = beanFactory;
}
// 這是BeanNameAware接口方法
@Override
public void setBeanName(String s) {
System.out.println("第11步:【執行BeanNameAware接口的setBeanName方法】屬性注入後調用, 此時s = "+s);
this.beanName = s;
}
// 這是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("第15步:【執行InitializingBean接口的afterPropertiesSet方法】在processBeforeInitialization之後,配置的xml_init之前調用");
}
// 這是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("第20步:【執行DiposibleBean接口的destroy方法】在processAfterInitialization之後,配置的xml_destroy之前調用");
}
}
2)BeanFactoryPostProcessor類(工廠後處理器)
/**
* @author xf
* @description 工廠後處理器
* @date 2019/5/22 14:05
*/
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
public CustomBeanFactoryPostProcessor() {
System.out.println("第1步:這是BeanFactoryPostProcessor(工廠後處理器)實現類CustomBeanFactoryPostProcessor的構造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("第2步:調用BeanFactoryPostProcessor(工廠後處理器)實現類CustomBeanFactoryPostProcessor的方法postProcessBeanFactory。ApplicationContext容器初始化中refresh()中調用");
}
}
3)BeanPostProcessor類
/**
* @author xf
* @description BeanPostProcessor的實現類
* @date 2019/5/22 14:06
*/
public class InitialBeanPostProcessor implements BeanPostProcessor {
public InitialBeanPostProcessor() {
System.out.println("第4步:這是BeanPostProcessor實現類(InitialBeanPostProcessor)的構造器!!");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第14步:postProcessBeforeInitialization(BeanPostProcessor接口實現類InitialBeanPostProcessor的方法)對屬性進行更改, bean = " + bean.getClass());
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第18步:postProcessAfterInitialization(BeanPostProcessor接口的方法)對屬性進行更改, bean = " + bean.getClass());
return bean;
}
}
4)InstantiationAwareBeanPostProcessor 接口本質是BeanPostProcessor的子接口,一般我們繼承Spring爲其提供的適配器類InstantiationAwareBeanPostProcessor Adapter來使用它
/**
* @author xf
* @description 實例化處理器
* @date 2019/5/22 14:12
*/
public class InstanceBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
public InstanceBeanPostProcessor() {
System.out.println("第3步:這是InstantiationAwareBeanPostProcessorAdapter實現類(InstanceBeanPostProcessor)構造器!!");
}
//實例化bean之前調用
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("第5步:實例化"+beanClass.getName()+"之前調用,即調用"+beanClass.getName()+"類構造函數之前調用 ");
return super.postProcessBeforeInstantiation(beanClass, beanName);
}
//實例化bean之後調用
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("第7步:返回boolean,bean實例化後調用,並且返回false則不會注入屬性");
return super.postProcessAfterInstantiation(bean, beanName);
}
// 設置bean的某個屬性時調用
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("第8步:postProcessProperties,在屬性注入之前調用;beanName = " + beanName + ";屬性名集合 : " + Arrays.toString(pvs.getPropertyValues()));
return super.postProcessProperties(pvs, bean, beanName);
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第13步:postProcessBeforeInitialization(InstantiationAwareBeanPostProcessorAdapter實現類InstanceBeanPostProcessor的方法) ");
return super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第17步:postProcessAfterInitialization(InstantiationAwareBeanPostProcessorAdapter類的實現方法) ");
return super.postProcessAfterInitialization(bean, beanName);
}
}
5)Spring Bean的配置文件spring-bean.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"
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.xsd">
<bean id="beanFactoryPostProcessor" class="com.spring.springbeancycle.CustomBeanFactoryPostProcessor">
</bean>
<bean id="instantiationAwareBeanPostProcessor" class="com.spring.springbeancycle.InstanceBeanPostProcessor">
</bean>
<bean id="beanPostProcessor" class="com.spring.springbeancycle.InitialBeanPostProcessor">
</bean>
<bean id="customBean" class="com.spring.springbeancycle.CustomBean" init-method="xml_init" destroy-method="xml_destroy">
<property name="name" value="小明"></property>
<property name="address" value="天涯海角"></property>
</bean>
</beans>
6)測試類
/**
* @author xf
* @description 測試類
* @date 2019/5/22 14:23
*/
public class SpringBeanTest {
public static void main(String[] args) {
System.out.println("====現在開始初始化容器====");
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:spring-bean.xml");
System.out.println("====容器初始化成功====");
CustomBean customBean = (CustomBean)context.getBean("customBean");
System.out.println("第19步:customBean = " + customBean);
System.out.println("====現在開始關閉容器!====");
((ClassPathXmlApplicationContext)context).close();
}
}
7)測試結果
第1步:這是BeanFactoryPostProcessor(工廠後處理器)實現類CustomBeanFactoryPostProcessor的構造器!!
第2步:調用BeanFactoryPostProcessor(工廠後處理器)實現類CustomBeanFactoryPostProcessor的方法postProcessBeanFactory。ApplicationContext容器初始化中refresh()中調用
第3步:這是InstantiationAwareBeanPostProcessorAdapter實現類(InstanceBeanPostProcessor)構造器!!
第4步:這是BeanPostProcessor實現類(InitialBeanPostProcessor)的構造器!!
第5步:實例化com.spring.springbeancycle.CustomBean之前調用,即調用com.spring.springbeancycle.CustomBean類構造函數之前調用
第6步:【構造器】調用CustomBean的構造器實例化
第7步:返回boolean,bean實例化後調用,並且返回false則不會注入屬性
第8步:postProcessProperties,在屬性注入之前調用;beanName = customBean;屬性名集合 : [bean property 'name', bean property 'address']
第9步:【注入屬性】注入屬性name
第10步:【注入屬性】注入屬性address
第11步:【執行BeanNameAware接口的setBeanName方法】屬性注入後調用, 此時s = customBean
第12步:【執行BeanFactoryAware接口的setBeanFactory方法】setBeanName後調用
第13步:postProcessBeforeInitialization(InstantiationAwareBeanPostProcessorAdapter實現類InstanceBeanPostProcessor的方法)
第14步:postProcessBeforeInitialization(BeanPostProcessor接口實現類InitialBeanPostProcessor的方法)對屬性進行更改, bean = class com.spring.springbeancycle.CustomBean
第15步:【執行InitializingBean接口的afterPropertiesSet方法】在processBeforeInitialization之後,配置的xml_init之前調用
第16步:【init-method】調用<bean>的init-method屬性指定的初始化方法
第17步:postProcessAfterInitialization(InstantiationAwareBeanPostProcessorAdapter類的實現方法)
第18步:postProcessAfterInitialization(BeanPostProcessor接口的方法)對屬性進行更改, bean = class com.spring.springbeancycle.CustomBean
====容器初始化成功====
第19步:customBean = CustomBean{name='小明', address='天涯海角'}
====現在開始關閉容器!====
第20步:【執行DiposibleBean接口的destroy方法】在processAfterInitialization之後,配置的xml_destroy之前調用
第21步:【destroy-method】調用<bean>的destroy-method屬性指定的銷燬方法
4、流程總結
1、實例化一個Bean--也就是我們常說的new;
2、按照Spring上下文對實例化的Bean進行配置--也就是IOC注入;
3、如果這個Bean已經實現了BeanNameAware接口,會調用它實現的setBeanName(String)方法,此處傳遞的就是Spring配置文件中Bean的id值
4、如果這個Bean已經實現了BeanFactoryAware接口,會調用它實現的setBeanFactory(setBeanFactory(BeanFactory)傳遞的是Spring工廠自身(可以用這個方式來獲取其它Bean,只需在Spring配置文件中配置一個普通的Bean就可以);
5、如果這個Bean已經實現了ApplicationContextAware接口,會調用setApplicationContext(ApplicationContext)方法,傳入Spring上下文(同樣這個方式也可以實現步驟4的內容,但比4更好,因爲ApplicationContext是BeanFactory的子接口,有更多的實現方法);
6、如果這個Bean關聯了BeanPostProcessor接口,將會調用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor經常被用作是Bean內容的更改,並且由於這個是在Bean初始化結束時調用那個的方法,也可以被應用於內存或緩存技術;
7、如果Bean在Spring配置文件中配置了init-method屬性會自動調用其配置的初始化方法。
8、如果這個Bean關聯了BeanPostProcessor接口,將會調用postProcessAfterInitialization(Object obj, String s)方法、;
注:以上工作完成以後就可以應用這個Bean了,那這個Bean是一個Singleton的,所以一般情況下我們調用同一個id的Bean會是在內容地址相同的實例,當然在Spring配置文件中也可以配置非Singleton,這裏我們不做贅述。
9、當Bean不再需要時,會經過清理階段,如果Bean實現了DisposableBean這個接口,會調用那個其實現的destroy()方法;
10、最後,如果這個Bean的Spring配置中配置了destroy-method屬性,會自動調用其配置的銷燬方法。
參考地址:
https://www.cnblogs.com/zrtqsk/p/3735273.html
https://uule.iteye.com/blog/2094609
https://blog.csdn.net/a327369238/article/details/52193822
https://www.cnblogs.com/kenshinobiy/p/4652008.html