1. 程式人生 > >spring framework 4 原始碼閱讀(2)---從ClassPathXmlApplicationContext開始

spring framework 4 原始碼閱讀(2)---從ClassPathXmlApplicationContext開始

Application初始化日誌

15:23:12.790 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
15:23:12.797 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
15:23:12.797 [main] DEBUG o.s.core.env.StandardEnvironment - Initialized StandardEnvironment with PropertySources [systemProperties,systemEnvironment]
//初始化Environment
15:23:12.803 [main] INFO  o.s.c.s.ClassPathXmlApplicationContext - Refreshing org
[email protected]
480a6370: startup date [Mon Aug 25 15:23:12 CST 2014]; root of context hierarchy 15:23:12.861 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemProperties] PropertySource with lowest search precedence 15:23:12.862 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence 15:23:12.862 [main] DEBUG o.s.core.env.StandardEnvironment - Initialized StandardEnvironment with PropertySources [systemProperties,systemEnvironment] //讀取XML 15:23:12.880 [main] INFO o.s.b.f.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [simpleContext.xml] 15:23:12.885 [main] DEBUG o.s.b.f.xml.DefaultDocumentLoader - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl] 15:23:12.928 [main] DEBUG o.s.b.factory.xml.BeansDtdResolver - Found beans DTD [http://www.springframework.org/dtd/spring-beans-2.0.dtd] in classpath: spring-beans-2.0.dtd //讀取BeanDefinition 15:23:12.953 [main] DEBUG o.s.b.f.x.DefaultBeanDefinitionDocumentReader - Loading bean definitions //解析XML 15:23:12.971 [main] DEBUG o.s.b.f.x.BeanDefinitionParserDelegate - No XML 'id' specified - using 'simpleBean' as bean name and [] as aliases 15:23:12.986 [main] DEBUG o.s.b.f.x.BeanDefinitionParserDelegate - No XML 'id' specified - using 'anotherBean' as bean name and [] as aliases 15:23:12.986 [main] DEBUG o.s.b.f.xml.XmlBeanDefinitionReader - Loaded 3 bean definitions from location pattern [simpleContext.xml] //將獲取到的BeanDefined設定到BeanFactory中 15:23:12.987 [main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Bean factory for org
[email protected]
480a6370: org.s[email protected]74bdaaa: defining beans [simpleBean,property,anotherBean]; root of factory hierarchy //初始化MessageSource,I18N中使用 15:23:13.025 [main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Unable to locate MessageSource with name 'messageSource': using default [
[email protected]
6c5f] //application事件中心 15:23:13.029 [main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.[email protected]5629fbc9]

一些bean的初始化

一個簡單的bean,裡面有個屬性property,以及test方法和需要進行屬性注入的setProperty
/**
 * 基本的bean方便測試
 * Created by zhangya on 2014/8/13.
 */
public class SimpleBean
{
	private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBean.class);
	private SimpleBeanProperty property;

	/**
	 * 簡單測試方法
	 */
	public void test()
	{
		LOGGER.info("SimpleBean is loading.");
		property.propertyTest();
	}

	/**
	 * 設定屬性 property
	 * <p>記錄日誌
	 * @param property
	 */
	public void setProperty(SimpleBeanProperty property)
	{
		LOGGER.info("Property is setting.");
		this.property = property;
	}
}

作為屬性賦值的bean,裡面包含初始化方法

/**
 * 作為屬性初始化的bean
 * Created by zhangya on 2014/8/13.
 */
public class SimpleBeanProperty
{
	private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBeanProperty.class);
	private String simpleVariable = "test567";
	public SimpleBeanProperty()
	{
		LOGGER.info("SimpleBeanProperty is loading.");
	}

	/**
	 * property的test方法
	 */
	public void propertyTest()
	{
		LOGGER.info("propertyTest method is invoking.{}",this);
	}

	/**
	 * 設定變數
	 * @param simpleVariable
	 */
	public void setSimpleVariable(String simpleVariable)
	{
		this.simpleVariable = simpleVariable;
	}

	/**
	 * 獲取變數的值
	 * @return 變數的值
	 */
	public String getSimpleVariable()
	{
		return simpleVariable;
	}

	@Override
	public String toString()
	{
		return "SimpleBeanProperty{" +
				"simpleVariable='" + simpleVariable + '\'' +
				'}';
	}
}

另外一個

/**
 * 用於初始化的另外一個bean
 * @author zhangya
 * @category com.letume.spring.study.init
 * @since 2014/8/24
 */
public class SimpleAnotherBean
{
	private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBeanProperty.class);
	private String simpleVariable = "test123";

	public SimpleAnotherBean()
	{
		LOGGER.info("SimpleAnotherBean is loading.");
	}

	/**
	 * property的test方法
	 */
	public void test()
	{
		LOGGER.info("test method is invoking.{}",this);
	}

	/**
	 * 設定變數
	 * @param simpleVariable
	 */
	public void setSimpleVariable(String simpleVariable)
	{
		this.simpleVariable = simpleVariable;
	}

	@Override
	public String toString()
	{
		return "SimpleAnotherBean{" +
				"simpleVariable='" + simpleVariable + '\'' +
				'}';
	}
}

simpleContext.xml applicationContext的配置檔案,這裡使用xml形式對bean進行配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
        "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
    <bean name="simpleBean"
          class="com.letume.spring.study.init.SimpleBean">
        <property name="property"><ref local="property"/> </property>
    </bean>
    <bean id="property" name="property"
          class="com.letume.spring.study.init.SimpleBeanProperty" scope="prototype"/>
    <bean name="anotherBean"
          class="com.letume.spring.study.init.SimpleAnotherBean" scope="prototype"/>
</beans>

下面是main函式,

例1 普通的bean初始化呼叫過程

/**
 * 簡單的spring類載入的方法
 * <pre>
 * ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(PATH+RESOURCE_CONTEXT);
 * SimpleBean simpleBean = context.getBean(SimpleBean.class)
 * simpleLoaderSimpleBean.test();
 * </pre>
 * Created by mitchz on 2014/8/13.
 */
public class SimpleInit
{

	private static final String PATH = "";
	private static final String RESOURCE_CONTEXT = "simpleContext.xml";

	public static void main(String[] args) throws InterruptedException
	{
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
				PATH + RESOURCE_CONTEXT);
		//獲取simpleBean
		SimpleBean simpleBean = context
				.getBean("simpleBean", SimpleBean.class);
		simpleBean.test();
		//context.registerShutdownHook();
	}
}
看下日誌:
---執行單例的初始化(為什麼會使用單例)
14:36:48.766 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Pre-instantiating singletons in org.s[email protected]29d8a2c5: defining beans [simpleBean,property,anotherBean]; root of factory hierarchy
14:36:48.767 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'simpleBean'
---建立bean例項
14:36:48.767 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'simpleBean'
14:36:48.786 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'simpleBean' to allow for resolving potential circular references
---建立屬性的例項
14:36:48.799 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'property'
14:36:48.799 [main] INFO  c.l.s.study.init.SimpleBeanProperty - SimpleBeanProperty is loading.
14:36:48.799 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'property'
---賦值
14:36:48.838 [main] INFO  c.l.spring.study.init.SimpleBean - Property is setting.
14:36:48.840 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'simpleBean'


....


---getBean的方法執行時,則直接從cache中取,之前初始化的例項
14:36:48.847 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'simpleBean'
14:36:48.847 [main] INFO  c.l.spring.study.init.SimpleBean - SimpleBean is loading.SimpleBean{property=SimpleBeanProperty{simpleVariable='test567'}}
14:36:48.849 [main] INFO  c.l.s.study.init.SimpleBeanProperty - propertyTest method is invoking.SimpleBeanProperty{simpleVariable='test567'}

從日誌中可以看出bean在沒有設定scope的時候,預設值為singletone的。另外即使屬性類是protetype的時候,也會在父bean初始化將其填充。不會在呼叫父bean的時候,重新初始化屬性所關聯的bean。詳細見例2

例2,在執行過程中,增加屬性修改,咱們再來執行下看看

		//修改property bean例項中的變數simpleVariable
		simpleBean.getProperty().setSimpleVariable("aaaaa");
		//重新獲取simpleBean例項
		simpleBean = context
				.getBean("simpleBean", SimpleBean.class);
		//再次執行test方法
		simpleBean.test();
看下新增的日誌:
15:14:58.447 [main] INFO  c.l.spring.study.init.SimpleBean - SimpleBean is loading.SimpleBean{property=SimpleBeanProperty{simpleVariable='aaaaa'}}
15:14:58.447 [main] INFO  c.l.s.study.init.SimpleBeanProperty - propertyTest method is invoking.SimpleBeanProperty{simpleVariable='aaaaa'}
看來咱們之前的猜測是對的,

第一、bean的scope預設為SingleTone的

第二、bean的lazyInit為false的

第三、即使屬性為prototype也不會再父bean為SingleTone的時重新初始化

例3、再增加兩行

		//獲取property例項
		SimpleBeanProperty property = context
				.getBean("property", SimpleBeanProperty.class);
		//測試propertyTest方法
		property.propertyTest();

再看下執行後新增的日誌:
15:19:10.331 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'property'
15:19:10.331 [main] INFO  c.l.s.study.init.SimpleBeanProperty - SimpleBeanProperty is loading.
15:19:10.331 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'property'
15:19:10.331 [main] INFO  c.l.s.study.init.SimpleBeanProperty - propertyTest method is invoking.SimpleBeanProperty{simpleVariable='test567'}
由於property的bean由於是prototype的,所以被重新初始化了。

例4、再增加四行:

		//獲取anotherBean例項
		SimpleAnotherBean anotherBean = context
				.getBean("anotherBean", SimpleAnotherBean.class);
		anotherBean.test();
		//設定變數的值
		anotherBean.setSimpleVariable("bbbbb");
		//重新獲取anotherBean例項
		anotherBean = context
				.getBean("anotherBean", SimpleAnotherBean.class);
		anotherBean.test();

大家在看下執行日誌:
15:23:13.130 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'anotherBean'
15:23:13.130 [main] INFO  c.l.s.study.init.SimpleBeanProperty - SimpleAnotherBean is loading.
15:23:13.130 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'anotherBean'
15:23:13.130 [main] INFO  c.l.s.study.init.SimpleBeanProperty - test method is invoking.SimpleAnotherBean{simpleVariable='test123'}
15:23:13.131 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'anotherBean'
15:23:13.131 [main] INFO  c.l.s.study.init.SimpleBeanProperty - SimpleAnotherBean is loading.
15:23:13.131 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'anotherBean'
15:23:13.131 [main] INFO  c.l.s.study.init.SimpleBeanProperty - test method is invoking.SimpleAnotherBean{simpleVariable='test123'}
bean為prototype的時候,每次都會被新初始化的

通過日誌的內容,梳理一下大概初始化邏輯


可以看出主要針對beans context 還有core包。
具體怎麼相互協作的,下一篇會進一步介紹。