做一個合格的程式猿之淺析Spring IoC原始碼(十)Spring Bean的初始化順序
上幾節我們比較詳細地說明了一下BeanFactoryPostProcessor和BeanPostProcessor這2個介面的作用和意義,並且也花了一個章節,講了一下BeanFactory和FactoryBean的關係,最後我們也稍微說明了一下BeanFactoryAware和BeanNameAware這兩個介面的作用,這一節,將開始講一下,一個bean在被spring管理的時候,初始化時的順序
我們定義一個簡單的bean實現BeanFactoryPostProcessor,BeanPostProcessor,BeanNameAware,
BeanFactoryAware,InitializingBean這些介面,並且呼叫init-method,我們觀察一下這些介面的具體實現的順序,為我們下一節分析refresh做好最後的準備
照舊上程式碼
SpringSimpleMultiBean.java
spring-init.xmlpackage org.study.spring.springinit; 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.InitializingBean; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; public class SpringSimpleMultiBean implements BeanFactoryAware,BeanNameAware,BeanFactoryPostProcessor,BeanPostProcessor,InitializingBean{ private Integer id; private String name; /** * 建構函式 */ public SpringSimpleMultiBean() { System.out.println("建構函式 init"); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } /** * init-method */ public void initMethod(){ System.out.println("init method Begin"); } public void say(){ System.out.println("hello I am "+name); } /** * InitializingBean介面的具體實現 */ public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean介面的具體實現 begin and id is "+ id +" and name is "+ name); } /** * BeanPostProcessor介面 before 初始化 */ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("BeanPostProcessor介面 before 初始化 postProcessAfterInitialization begin"); return bean; } /** * BeanPostProcessor介面after 初始化 */ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("BeanPostProcessor介面after 初始化 postProcessAfterInitialization begin"); return bean; } /** * BeanFactoryPostProcessor 介面初始化 */ public void postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("BeanFactoryPostProcessor 介面初始化 begin and this beanFactory is "+beanFactory); } /** * BeanNameAware初始化 */ public void setBeanName(String name) { System.out.println("BeanNameAware初始化 set BeanName begin and name is "+name); } /** * BeanFactoryName初始化 */ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("BeanFactoryName初始化 begin and beanFactory is "+beanFactory); } }
SpringSimpleMultiBeanTest.java<?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" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <bean id="springMultiBean" class="org.study.spring.springinit.SpringSimpleMultiBean" init-method="initMethod"> <property name="id" value="1"/> <property name="name" value="spring"/> </bean> <!-- <bean id="springOtherBean" class="org.study.spring.springinit.SpringOtherBean"></bean> --> </beans>
package org.study.spring.springinit;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringSimpleMultiBeanTest {
@Test
public void test2() throws Exception{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-init.xml");
SpringSimpleMultiBean bean = applicationContext.getBean("springMultiBean",SpringSimpleMultiBean.class);
bean.say();
// SpringOtherBean springOtherBean = applicationContext.getBean("springOtherBean",SpringOtherBean.class);
// springOtherBean.say();
}
}
執行結果:
好了,我發現我不貼程式碼已經說明不了問題了,語言能力太差,我們先來看看結果吧~
①首先執行的是建構函式
②然後執行的BeanNameAware這個介面中的方法
③然後執行的是BeanFactoryAware這個介面中的方法
④執行InitializingBean介面中的afterPropertiesSet的方法
⑤執行我們在xml中定義的init-method這個方法
⑥最後執行的是BeanFactoryPostProcessor這個方法
這個執行結果我們可以清晰的瞭解spring的初始化流程,但你可以看出BeanPostProcessor並沒有初始化,這是為什麼呢?
我們再次開啟BeanPostProcessor.java的原始碼
翻譯一下:應用這個BeanPostProcessor來返回一個新的bean的例項,當任何Bean回撥的時候~
請注意是回撥~
好吧,意思很明顯,當其他非實現BeanPostProcessor的bean且在同一個容器的bean在初始化的時候,才會回撥這個方法,所以這就理解了,為什麼,我們這邊沒有執行的原因了,因為此時spring就管理了一個bean,沒有其他的bean,何來的回撥呢?
好吧,我們開啟上面程式碼的SpringSimpleMultiBeanTest.java中17~18行的註釋,spring-init.xml中19行的註釋
好了,這次運行了,最後盜圖一張
好了,spring的元件我們講了好幾個了,也講了這些元件在spring初始化bean時候執行的順序,下一節我們分析refresh()這個方法,應該會理解為什麼會是這個執行順序了,END~