上篇文章我們介紹了Spring Bean的初始化流程,在最後我們提到在通過populateBean方法調用後,調用了initializeBean方法,實現了一些列例如BeanNameAware、BeanPostProcessor等擴展接口的調用,本篇文章我們就來看一下Spring提供給開發者的一些擴展接口。
Spring框架運用了非常多的設計模式,從整體上看,它的設計嚴格遵循了OCP——開閉原則:
- 對修改關閉,外部無法修改Spring整個運作的流程
- 對擴展開放,可以通過繼承、實現Spring提供的衆多抽象類與接口來改變類加載的行爲
本篇文章介紹的擴展接口就體現了對擴展開放的原則。
1. InitializingBean&DisposableBean
InitializingBean接口中提供了方法afterPropertiesSet(),DisposableBean接口中提供了方法destroy()。這兩個接口功能類似,InitializingBean接口的afterPropertiesSet()方法用於Bean屬性設置完畢(在invokeInitMethods方法中調用),做一些初始化操作。DisposableBean接口的destroy()方法用於Bean生命週期結束前(DefaultSingletonBeanRegistry的destroyBean方法調中調用)做一些收尾工作。
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
void destroy() throws Exception;
}
下面我們來看一個示例:
public class TestBean implements InitializingBean, DisposableBean {
private String testName;
public void setTestName(String testName) {
System.out.println("Call TestBean.setName()");
this.testName = testName;
}
public void destroy() throws Exception {
System.out.println("Call TestBean.destroy(), DisposableBean");
}
public void afterPropertiesSet() throws Exception {
System.out.println("Call TestBean.afterPropertiesSet(), InitializingBean");
}
public void initMethod() {
System.out.println("Call TestBean.initMethod(), init-method");
}
public void destroyMethod() {
System.out.println("Call TestBean.destroyMethod(), 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<bean id="testBean" class="com.zhuoli.service.spring.explore.extend.TestBean" init-method="initMethod" destroy-method="destroyMethod">
<property name="testName" value="testName"/>
</bean>
</beans>
public class SpringExtendsTest {
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-extends.xml");
TestBean testBean = (TestBean) applicationContext.getBean("testBean");
applicationContext.close();
}
}
執行結果:
Call TestBean.setName()
Call TestBean.afterPropertiesSet(), InitializingBean
Call TestBean.initMethod(), init-method
Call TestBean.destroy(), DisposableBean
Call TestBean.destroyMethod(), destroy-method
可以看到執行順序爲set方法、InitializingBean的afterPropertiesSet方法、bean init-method指定的初始化方法、DisposableBean的destroy方法、bean的destroy-method指定的銷燬方法。
其實也好解釋,通過上一篇文章我們知道setName方法是在populateBean方法中調用的,所以最先調用。InitializingBean的afterPropertiesSet方法是通過populateBean後面的方法initializeBean中調用的invokeInitMethods中調用的,並且調用在init-method之前,所以之後InitializingBean的afterPropertiesSet方法會被調用,接着纔是init-method。
關於這幾個接口,這裏總結幾點:
- InitializingBean接口、Disposable接口可以和Bean的屬性init-method、destory-method配合使用,接口的優先級大於Bean的屬性
- InitializingBean接口、Disposable接口方法的調用底層使用類型強轉.方法名()進行直接方法調用,init-method、destory-method底層使用反射,前者和Spring耦合程度更高但效率高,後者解除了和Spring之間的耦合但是效率低(關於效率高低,這點不好講,只是“理論之談,反射也並不一定就比直接方法調用效率低很多。至於使用哪種方式,純憑個人喜好)
- afterPropertiesSet()方法是在Bean的屬性設置之後纔會進行調用,某個Bean的afterPropertiesSet()方法執行完畢纔會執行下一個Bean的afterPropertiesSet()方法,因此不建議在afterPropertiesSet()方法中寫處理時間太長的方法
2. Aware接口
這裏我們介紹BeanNameAware、ApplicationContextAware和BeanFactoryAware這三個Aware相關的接口。Aware的意思是”感知的”,顧名思義,這三個接口的意思也與“感知”相關。
- 實現BeanNameAware接口的Bean,可以在Bean加載的過程中獲取該Bean的id
- 實現ApplicationContextAware接口的Bean,可以在Bean加載的過程中獲取Spring的上下文ApplicationContext,從ApplicationContext中可以獲取包括任意的Bean以及大量Spring容器內容和信息
- 實現BeanFactoryAware接口的Bean,可以在Bean加載的過程中獲取加載該Bean的BeanFactory
下面來看個例子:
public class AwareBean implements InitializingBean, BeanNameAware, BeanFactoryAware, ApplicationContextAware {
private String beanName;
private ApplicationContext applicationContext;
private BeanFactory beanFactory;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Call AwareBean.afterPropertiesSet(), InitializingBean");
}
public void setBeanName(String beanName) {
System.out.println("Call AwareBean.setBeanName(), beanName = " + beanName);
this.beanName = beanName;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("Call AwareBean.setApplicationContext(), applicationContext = " + applicationContext);
this.applicationContext = applicationContext;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("Call AwareBean.setBeanFactory(), beanFactory = " + beanFactory);
this.beanFactory = beanFactory;
}
}
<?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-4.1.xsd">
<bean id="awareBean" class="com.zhuoli.service.spring.explore.aware.AwareBean" />
</beans>
public class AwareBeanTest {
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-aware.xml");
AwareBean awareBean = (AwareBean) applicationContext.getBean("awareBean");
applicationContext.close();
}
}
執行結果:
Call AwareBean.setBeanName(), beanName = awareBean
Call AwareBean.setBeanFactory(), beanFactory = org.springframework.beans.factory.support.DefaultListableBeanFactory@7a187f14: defining beans [awareBean]; root of factory hierarchy
Call AwareBean.setApplicationContext(), applicationContext = org.springframework.context.support.ClassPathXmlApplicationContext@7e32c033, started on Thu Apr 16 09:01:20 CST 2020
Call AwareBean.afterPropertiesSet(), InitializingBean
關於這三個接口,總結幾點:
- 如果你的BeanName、ApplicationContext、BeanFactory有用,那麼就自己定義一個變量將它們保存下來(如上面的成員變量beanName、applicationContext、beanFactory)。如果沒用,那麼只需要實現setXXX()方法,用一下Spring注入進來的參數即可
- 如果Bean同時還實現了InitializingBean,容器會保證BeanName、ApplicationContext和BeanFactory在調用afterPropertiesSet()方法前被注入,也就是說Aware接口的優先級大於InitializingBean接口
3. FactoryBean
傳統的Spring容器加載一個Bean的整個過程,都是由Spring控制的,開發者除了設置Bean相關屬性之外,是沒有太多的自主權的。FactoryBean改變了這一點,開發者可以個性化地定製自己想要實例化出來的Bean,方法就是實現FactoryBean接口。下面來看個例子:
public interface Car {
public void driving();
}
public class Bmw implements Car {
@Override
public void driving() {
System.out.println("Bmw driving");
}
}
public class Benz implements Car {
@Override
public void driving() {
System.out.println("Benz driving");
}
}
public class CarFactoryBean implements FactoryBean<Car> {
private String carName;
@Override
public boolean isSingleton() {
return true;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public Car getObject() throws Exception {
if (carName.equals("Bmw")) {
return new Bmw();
} else if (carName.equals("Benz")) {
return new Benz();
} else {
return null;
}
}
public void setCarName(String carName) {
this.carName = carName;
}
}
<?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-4.1.xsd">
<bean id="car" class="com.zhuoli.service.spring.explore.factorybean.CarFactoryBean">
<property name="carName" value="Bmw"/>
</bean>
</beans>
public class FactoryBeanTest {
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-factory-bean.xml");
Car car = (Car) applicationContext.getBean("car");
car.driving();
}
}
執行結果:
Bmw driving
當我們把spring-factory-bean.xml配置文件中的value改爲“Benz”時,同樣執行上述代碼,會得到執行結果:
Benz driving
所以通過FactoryBean,最後得到的並不是FactoryBean本身,而是FactoryBean的泛型對象,這就是FactoryBean的作用。FactoryBean的幾個方法:
- getObject():具體Bean的實例化過程
- getObjectType():接口返回的實例的Class對象
- isSingleton():返回該Bean是否爲一個單例的Bean
我們回頭看一下在面試中經常會問到的一個概念,BeanFactory和FactoryBean的關係?答案就非常明確了,這兩者之間其實沒有什麼可比較的關係,只是命名比較接近。BeanFactory是Bean工廠,控制所有Bean的生成,實現了Spring IOC的基本功能。而FactoryBean是一種特殊的Bean,爲IOC容器中的Bean提供了更加靈活的實現方式。
4. BeanPostProcessor
上面介紹的InitializingBean、DisposableBean、FactoryBean包括init-method和destory-method,都是針對某個Bean控制其初始化的操作,而似乎沒有一種辦法可以針對每個Bean的生成前後做一些邏輯操作,BeanPostProcessor可以幫我們做到這一點。BeanPostProcessor接口中定義了兩個方法:
- postProcessBeforeInitialization:在Bean初始化前調用
- postProcessAfterInitialization:在Bean初始化後調用
下面看個簡單的示例:
public class TestBean implements InitializingBean, DisposableBean {
private String testName;
public void setTestName(String testName) {
System.out.println("Call TestBean.setName()");
this.testName = testName;
}
public void destroy() throws Exception {
System.out.println("Call TestBean.destroy(), DisposableBean");
}
public void afterPropertiesSet() throws Exception {
System.out.println("Call TestBean.afterPropertiesSet(), InitializingBean");
}
public void initMethod() {
System.out.println("Call TestBean.initMethod(), init-method");
}
public void destroyMethod() {
System.out.println("Call TestBean.destroyMethod(), destroy-method");
}
}
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Call MyBeanPostProcessor.postProcessBeforeInitialization(), beanName = " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Call MyBeanPostProcessor.postProcessAfterInitialization(), beanName = " + beanName);
return bean;
}
}
<?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-4.1.xsd">
<bean id="testBean0" class="com.zhuoli.service.spring.explore.beanpostprocessor.TestBean" init-method="initMethod" destroy-method="destroyMethod">
<property name="testName" value="testName0"/>
</bean>
<bean id="testBean1" class="com.zhuoli.service.spring.explore.beanpostprocessor.TestBean" init-method="initMethod" destroy-method="destroyMethod">
<property name="testName" value="testName1"/>
</bean>
<bean id="myBeanPostProcessor" class="com.zhuoli.service.spring.explore.beanpostprocessor.MyBeanPostProcessor" />
</beans>
public class BeanPostProcessorTest {
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-bean-post-processor.xml");
applicationContext.close();
}
}
運行結果:
Call TestBean.setName()
Call TestBean.setBeanName(), BeanNameAware, beanName = testBean0
Call MyBeanPostProcessor.postProcessBeforeInitialization(), beanName = testBean0
Call TestBean.afterPropertiesSet(), InitializingBean
Call TestBean.initMethod(), init-method
Call MyBeanPostProcessor.postProcessAfterInitialization(), beanName = testBean0
Call TestBean.setName()
Call TestBean.setBeanName(), BeanNameAware, beanName = testBean1
Call MyBeanPostProcessor.postProcessBeforeInitialization(), beanName = testBean1
Call TestBean.afterPropertiesSet(), InitializingBean
Call TestBean.initMethod(), init-method
Call MyBeanPostProcessor.postProcessAfterInitialization(), beanName = testBean1
Call TestBean.destroy(), DisposableBean
Call TestBean.destroyMethod(), destroy-method
Call TestBean.destroy(), DisposableBean
Call TestBean.destroyMethod(), destroy-method
可以看到在每個Bean填充屬性(populateBean)之後,調用init-method之前,會執行Aware接口,BeanPostProcessor的postProcessBeforeInitialization方法和InitializingBean的afterPropertiesSet方法,並且優先級順序依次是Aware接口、BeanPostProcessor和InitializingBean。BeanPostProcessor的postProcessAfterInitialization方法會在每個Bean調用init-method之後執行。所以我們大致可以得到下面這個Bean生命週期圖:
另外需要注意的是,postProcessBeforeInitialization和postProcessAfterInitialization這兩個方法是有返回值的,不要返回null,否則getBean的時候拿不到對象。
5. BeanFactoryPostProcessor
Spring允許在Bean創建之前,讀取Bean的元屬性,並根據自己的需求對元屬性進行改變,比如將Bean的scope從singleton改變爲prototype,最典型的應用應當是PropertySourcesPlaceholderConfigurer,替換xml文件中的佔位符,替換爲properties文件中相應的key對應的value等。這些工作都可以在BeanFactoryPostProcessor中完成。下面來看示例:
新增一個類MyBeanFactoryPostProcessor,實現BeanFactoryPostProcessor接口。
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("Call TestBean.postProcessBeanFactory(), BeanFactoryPostProcessor");
}
}
新增一個類MyBeanPostProcessor,實現BeanPostProcessor接口。
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Call MyBeanPostProcessor.postProcessBeforeInitialization(), beanName = " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Call MyBeanPostProcessor.postProcessAfterInitialization(), beanName = " + beanName);
return bean;
}
}
新增一個測試Bean TestBean
public class TestBean implements BeanNameAware, InitializingBean, DisposableBean {
private String testName;
public void setTestName(String testName) {
System.out.println("Call TestBean.setName()");
this.testName = testName;
}
@Override
public void setBeanName(String s) {
System.out.println("Call TestBean.setBeanName(), BeanNameAware, beanName = " + s);
}
public void destroy() throws Exception {
System.out.println("Call TestBean.destroy(), DisposableBean");
}
public void afterPropertiesSet() throws Exception {
System.out.println("Call TestBean.afterPropertiesSet(), InitializingBean");
}
public void initMethod() {
System.out.println("Call TestBean.initMethod(), init-method");
}
public void destroyMethod() {
System.out.println("Call TestBean.destroyMethod(), destroy-method");
}
}
新增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-4.1.xsd">
<bean id="testBean0" class="com.zhuoli.service.spring.explore.beanfartorypostprocessor.TestBean" init-method="initMethod" destroy-method="destroyMethod">
<property name="testName" value="testName0"/>
</bean>
<bean id="testBean1" class="com.zhuoli.service.spring.explore.beanfartorypostprocessor.TestBean" init-method="initMethod" destroy-method="destroyMethod">
<property name="testName" value="testName1"/>
</bean>
<bean id="myBeanPostProcessor" class="com.zhuoli.service.spring.explore.beanfartorypostprocessor.MyBeanPostProcessor" />
<bean id="myBeanFactoryPostProcessor" class="com.zhuoli.service.spring.explore.beanfartorypostprocessor.MyBeanFactoryPostProcessor" />
</beans>
public class BeanFactoryPostProcessorTest {
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-bean-factory-post-processor.xml");
applicationContext.close();
}
}
運行結果:
Call TestBean.postProcessBeanFactory(), BeanFactoryPostProcessor
Call TestBean.setName()
Call TestBean.setBeanName(), BeanNameAware, beanName = testBean0
Call MyBeanPostProcessor.postProcessBeforeInitialization(), beanName = testBean0
Call TestBean.afterPropertiesSet(), InitializingBean
Call TestBean.initMethod(), init-method
Call MyBeanPostProcessor.postProcessAfterInitialization(), beanName = testBean0
Call TestBean.setName()
Call TestBean.setBeanName(), BeanNameAware, beanName = testBean1
Call MyBeanPostProcessor.postProcessBeforeInitialization(), beanName = testBean1
Call TestBean.afterPropertiesSet(), InitializingBean
Call TestBean.initMethod(), init-method
Call MyBeanPostProcessor.postProcessAfterInitialization(), beanName = testBean1
Call TestBean.destroy(), DisposableBean
Call TestBean.destroyMethod(), destroy-method
Call TestBean.destroy(), DisposableBean
Call TestBean.destroyMethod(), destroy-method
跟上述4介紹BeanPostProcessor唯一不同的地方在於,在調用set方法設置Bean屬性之前,調用了BeanFactoryPostProcessor的postProcessBeanFactory()方法,並且只調用了一次。所以可以看出:
- BeanFactoryPostProcessor的執行先於BeanPostProcessor
- BeanFactoryPostProcessor的postProcessBeanFactory()方法只會執行一次
結論也可以解釋,BeanFactoryPostProcessor中定義的方法是在AbstractApplicationContext類中的refresh()方法中調用invokeBeanFactoryPostProcessors()方法實現的,而Bean的初始化是在之後調用finishBeanFactoryInitialization()方法實現的。所以BeanFactoryPostProcessor的執行先於BeanPostProcessor。
同時我們注意到postProcessBeanFactory方法的參數類型是ConfigurableListableBeanFactory,這就是爲什麼可以使用BeanFactoryPostProcessor來改變Bean的屬性相對應起來了。ConfigurableListableBeanFactory功能非常豐富,它攜帶了每個Bean的基本信息。比如我們可以獲取如下信息:
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("Call TestBean.postProcessBeanFactory(), BeanFactoryPostProcessor");
BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition("common0");
MutablePropertyValues beanProperty = beanDefinition.getPropertyValues();
System.out.println("scope before change:" + beanDefinition.getScope());
beanDefinition.setScope("singleton");
System.out.println("scope after change:" + beanDefinition.getScope());
System.out.println("beanProperty:" + beanProperty);
}
}
6. InstantiationAwareBeanPostProcessor
上述介紹的幾個Bean擴展接口都作用於Bean的初始化過程,其實Bean構建還包括一個過程——實例化。而這裏要介紹的擴展接口InstantiationAwareBeanPostProcessor就是作用於這兩個階段,我們首先來看一下實例化和初始化的關係:
- 實例化:創建Bean的過程,即調用Bean的構造函數構造Bean實例
- 初始化:在Spring中的初始化可以理解爲在調用Bean的setter方法設置屬性後,調用init-method設置Bean的屬性這一階段
下面看個簡單的示例,來認識一下InstantiationAwareBeanPostProcessor。
public class TestBean implements BeanNameAware, InitializingBean, DisposableBean {
private String testName;
public TestBean() {
System.out.println("Call TestBean's constructor");
}
public void setTestName(String testName) {
System.out.println("Call TestBean.setName()");
this.testName = testName;
}
@Override
public void setBeanName(String s) {
System.out.println("Call TestBean.setBeanName(), BeanNameAware, beanName = " + s);
}
public void destroy() throws Exception {
System.out.println("Call TestBean.destroy(), DisposableBean");
}
public void afterPropertiesSet() throws Exception {
System.out.println("Call TestBean.afterPropertiesSet(), InitializingBean");
}
public void initMethod() {
System.out.println("Call TestBean.initMethod(), init-method");
}
public void destroyMethod() {
System.out.println("Call TestBean.destroyMethod(), destroy-method");
}
}
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Call MyBeanPostProcessor.postProcessBeforeInitialization(), beanName = " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Call MyBeanPostProcessor.postProcessAfterInitialization(), beanName = " + beanName);
return bean;
}
}
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public Object postProcessBeforeInstantiation(Class<?> bean, String beanName) throws BeansException {
System.out.println("Call MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(), InstantiationAwareBeanPostProcessor");
return null;
}
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("Call MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(), InstantiationAwareBeanPostProcessor");
return true;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Call MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization(), InstantiationAwareBeanPostProcessor");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Call MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization(), InstantiationAwareBeanPostProcessor");
return bean;
}
}
<?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-4.1.xsd">
<bean id="testBean0" class="com.zhuoli.service.spring.explore.instantiationawarebeanpostprocessor.TestBean" init-method="initMethod" destroy-method="destroyMethod">
<property name="testName" value="testName"/>
</bean>
<bean id="myBeanPostProcessor" class="com.zhuoli.service.spring.explore.beanpostprocessor.MyBeanPostProcessor" />
<bean id="myInstantiationAwareBeanPostProcessor" class="com.zhuoli.service.spring.explore.instantiationawarebeanpostprocessor.MyInstantiationAwareBeanPostProcessor" />
</beans>
public class InstantiationAwareBeanPostProcessorTest {
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-instantiation-aware-bean-post-processor.xml");
applicationContext.close();
}
}
運行結果:
Call MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(), InstantiationAwareBeanPostProcessor
Call TestBean's constructor
Call MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(), InstantiationAwareBeanPostProcessor
Call TestBean.setName()
Call TestBean.setBeanName(), BeanNameAware, beanName = testBean0
Call MyBeanPostProcessor.postProcessBeforeInitialization(), beanName = testBean0
Call MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization(), InstantiationAwareBeanPostProcessor
Call TestBean.afterPropertiesSet(), InitializingBean
Call TestBean.initMethod(), init-method
Call MyBeanPostProcessor.postProcessAfterInitialization(), beanName = testBean0
Call MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization(), InstantiationAwareBeanPostProcessor
Call TestBean.destroy(), DisposableBean
Call TestBean.destroyMethod(), destroy-method
可以看出以下幾點:
- postProcessBeforeInstantiation()方法會在調用構造方法實例化前調用
- postProcessAfterInstantiation()方法會在構造函數方法結束後調用
- InstantiationAwareBeanPostProcessor從BeanPostProcessor中繼承的方法跟普通的BeanPostProcessor一樣,會在init-method方法前後調用
通常來講,我們不會直接實現InstantiationAwareBeanPostProcessor接口,而是會採用繼承InstantiationAwareBeanPostProcessorAdapter這個抽象類的方式來使用。
加上InstantiationAwareBeanPostProcessor,我們再來看一下Bean的初始化流程:
參考鏈接:
1. Spring源碼