1. 程式人生 > >做一個合格的程式猿之淺析Spring IoC原始碼(十)Spring Bean的初始化順序

做一個合格的程式猿之淺析Spring IoC原始碼(十)Spring Bean的初始化順序

上幾節我們比較詳細地說明了一下BeanFactoryPostProcessor和BeanPostProcessor這2個介面的作用和意義,並且也花了一個章節,講了一下BeanFactory和FactoryBean的關係,最後我們也稍微說明了一下BeanFactoryAware和BeanNameAware這兩個介面的作用,這一節,將開始講一下,一個bean在被spring管理的時候,初始化時的順序

我們定義一個簡單的bean實現BeanFactoryPostProcessorBeanPostProcessor,BeanNameAware,

BeanFactoryAware,InitializingBean這些介面,並且呼叫init-method,我們觀察一下這些介面的具體實現的順序,為我們下一節分析refresh做好最後的準備

照舊上程式碼

SpringSimpleMultiBean.java

package 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);
	}

}
spring-init.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" 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>
SpringSimpleMultiBeanTest.java
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~