Spring源碼閱讀入門(mén)指引
本文說(shuō)明2點(diǎn):
1.閱讀源碼的入口在哪里?
2.入門(mén)前必備知識(shí)了解:IOC和AOP
一、我們從哪里開(kāi)始
1.準(zhǔn)備工作:在官網(wǎng)上下載了Spring源代碼之后,導(dǎo)入Eclipse,以方便查詢(xún)。
2.打開(kāi)我們使用Spring的項(xiàng)目工程,找到Web.xml這個(gè)網(wǎng)站系統(tǒng)配置文件,在其中找到Spring的初始化信息:
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
由配置信息可知,我們開(kāi)始的入口就這里ContextLoaderListener這個(gè)監(jiān)聽(tīng)器。
在源代碼中我們找到了這個(gè)類(lèi),它的定義是:
- public class ContextLoaderListener extends ContextLoader
- implements ServletContextListener {
- …
- /**
- * Initialize the root web application context.
- */
- public void contextInitialized(ServletContextEvent event) {
- this.contextLoader = createContextLoader();
- if (this.contextLoader == null) {
- this.contextLoader = this;
- }
- this.contextLoader.initWebApplicationContext(event.getServletContext());
- }
- ...
- }
該類(lèi)繼續(xù)了ContextLoader并實(shí)現(xiàn)了監(jiān)聽(tīng)器,關(guān)于Spring的信息載入配置、初始化便是從這里開(kāi)始了,具體其他閱讀另外寫(xiě)文章來(lái)深入了解。
二、關(guān)于IOC和AOP
關(guān)于Spring IOC 網(wǎng)上很多相關(guān)的文章可以閱讀,那么我們從中了解到的知識(shí)點(diǎn)是什么?
1)IOC容器和AOP切面依賴(lài)注入是Spring是核心。
IOC容器為開(kāi)發(fā)者管理對(duì)象之間的依賴(lài)關(guān)系提供了便利和基礎(chǔ)服務(wù),其中Bean工廠(BeanFactory)和上下文(ApplicationContext)就是IOC的表現(xiàn)形式
BeanFactory是個(gè)接口類(lèi),只是對(duì)容器提供的最基本服務(wù)提供了定義,而DefaultListTableBeanFactory、XmlBeanFactory、ApplicationContext等都是具體的實(shí)現(xiàn)。
接口:
- public interface BeanFactory {
- //這里是對(duì)工廠Bean的轉(zhuǎn)義定義,因?yàn)槿绻褂胋ean的名字檢索IOC容器得到的對(duì)象是工廠Bean生成的對(duì)象,
- //如果需要得到工廠Bean本身,需要使用轉(zhuǎn)義的名字來(lái)向IOC容器檢索
- String FACTORY_BEAN_PREFIX = "&";
- //這里根據(jù)bean的名字,在IOC容器中得到bean實(shí)例,這個(gè)IOC容器就象一個(gè)大的抽象工廠,用戶(hù)可以根據(jù)名字得到需要的bean
- //在Spring中,Bean和普通的JAVA對(duì)象不同在于:
- //Bean已經(jīng)包含了我們?cè)贐ean定義信息中的依賴(lài)關(guān)系的處理,同時(shí)Bean是已經(jīng)被放到IOC容器中進(jìn)行管理了,有它自己的生命周期
- Object getBean(String name) throws BeansException;
- //這里根據(jù)bean的名字和Class類(lèi)型來(lái)得到bean實(shí)例,和上面的方法不同在于它會(huì)拋出異常:如果根名字取得的bean實(shí)例的Class類(lèi)型和需要的不同的話。
- Object getBean(String name, Class requiredType) throws BeansException;
- //這里提供對(duì)bean的檢索,看看是否在IOC容器有這個(gè)名字的bean
- boolean containsBean(String name);
- //這里根據(jù)bean名字得到bean實(shí)例,并同時(shí)判斷這個(gè)bean是不是單件,在配置的時(shí)候,默認(rèn)的Bean被配置成單件形式,如果不需要單件形式,需要用戶(hù)在Bean定義信息中標(biāo)注出來(lái),這樣IOC容器在每次接受到用戶(hù)的getBean要求的時(shí)候,會(huì)生成一個(gè)新的Bean返回給客戶(hù)使用 - 這就是Prototype形式
- boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
- //這里對(duì)得到bean實(shí)例的Class類(lèi)型
- Class getType(String name) throws NoSuchBeanDefinitionException;
- //這里得到bean的別名,如果根據(jù)別名檢索,那么其原名也會(huì)被檢索出來(lái)
- String[] getAliases(String name);
- }
實(shí)現(xiàn):
XmlBeanFactory的實(shí)現(xiàn)是這樣的:
- public class XmlBeanFactory extends DefaultListableBeanFactory {
- //這里為容器定義了一個(gè)默認(rèn)使用的bean定義讀取器,在Spring的使用中,Bean定義信息的讀取是容器初始化的一部分,但是在實(shí)現(xiàn)上是和容器的注冊(cè)以及依賴(lài)的注入是分開(kāi)的,這樣可以使用靈活的 bean定義讀取機(jī)制。
- private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
- //這里需要一個(gè)Resource類(lèi)型的Bean定義信息,實(shí)際上的定位過(guò)程是由Resource的構(gòu)建過(guò)程來(lái)完成的。
- public XmlBeanFactory(Resource resource) throws BeansException {
- this(resource, null);
- }
- //在初始化函數(shù)中使用讀取器來(lái)對(duì)資源進(jìn)行讀取,得到bean定義信息。這里完成整個(gè)IOC容器對(duì)Bean定義信息的載入和注冊(cè)過(guò)程
- public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws
- BeansException {
- super(parentBeanFactory);
- this.reader.loadBeanDefinitions(resource);
- }
我們可以看到IOC容器使用的一些基本過(guò)程:
如:DefaultListableBeanFactory
- ClassPathResource res = new ClassPathResource("beans.xml");//讀取配置文件
- DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
- XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
- reader.loadBeanDefinitions(res);
這些代碼演示了以下幾個(gè)步驟:
1. 創(chuàng)建IOC配置文件的抽象資源
2. 創(chuàng)建一個(gè)BeanFactory,這里我們使用DefaultListableBeanFactory;
3. 創(chuàng)建一個(gè)載入bean定義信息的讀取器,這里使用XmlBeanDefinitionReader來(lái)載入XML形式的bean定義信息,配置給BeanFactory;
4. 從定義好的資源位置讀入配置信息,具體的解析過(guò)程由XmlBeanDefinitionReader來(lái)完成,這樣完成整個(gè)載入和注冊(cè)bean定義的過(guò)程。我們的IoC容器就建立起來(lái)了。
再簡(jiǎn)單的說(shuō),我的系統(tǒng)在啟動(dòng)時(shí)候,會(huì)完成的動(dòng)作就是:
1.由ResourceLoader獲取資源文件,也即bean的各種配置文件;
2.由BeanDefintion對(duì)配置文件的定義信息的載入;
3.用BeanDefinitionRegistry接口來(lái)實(shí)現(xiàn)載入bean定義信息并向IOC容器進(jìn)行注冊(cè)。
注意,IOC容器和上下文的初始化一般不包含Bean的依賴(lài)注入的實(shí)現(xiàn)。
2)AOP這個(gè)過(guò)程并不是在注冊(cè)bean的過(guò)程實(shí)現(xiàn)的。
我們只看到在處理相關(guān)的Bean屬性的時(shí)候,使用了RuntimeBeanReference對(duì)象作為依賴(lài)信息的紀(jì)錄。
在IOC容器已經(jīng)載入了用戶(hù)定義的Bean信息前提下,這個(gè)依賴(lài)注入的過(guò)程是用戶(hù)第一次向IOC容器索要Bean的時(shí)候觸發(fā)的,或者是我們可以在Bean定義信息中通過(guò)控制lazy-init屬性來(lái)使得容器完成對(duì)Bean的預(yù)實(shí)例化 - 這個(gè)預(yù)實(shí)例化也是一個(gè)完成依賴(lài)注入的過(guò)程。
我們說(shuō)明一下過(guò)程:
1.用戶(hù)想IOC容器請(qǐng)求Bean。
2.系統(tǒng)先在緩存中查找是否有該名稱(chēng)的Bean(去各個(gè)BeanFactory去查找)
3.沒(méi)有的話就去創(chuàng)建Bean并進(jìn)行依賴(lài)注入,并且這個(gè)請(qǐng)求將被記錄起來(lái)。
請(qǐng)求Bean具體的實(shí)現(xiàn):
代碼入口在DefaultListableBeanFactory的基類(lèi)AbstractBeanFactory中:
- public Object getBean(String name, Class requiredType, final Object[] args) throwsBeansException {
- ...
- Object sharedInstance = getSingleton(beanName);//先去緩存取
- if (sharedInstance != null) {
- ...
- if (containsBeanDefinition(beanName)) {
- RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false);
- bean = getObjectForBeanInstance(sharedInstance, name,mergedBeanDefinition);
- }
- else {
- bean = getObjectForBeanInstance(sharedInstance, name, null);
- }
- }
- else {
- }
- ...
- }
注入Bean具體的實(shí)現(xiàn):
具體的bean創(chuàng)建過(guò)程和依賴(lài)關(guān)系的注入在createBean中,這個(gè)方法在AbstractAutowireCapableBeanFactory中給出了實(shí)現(xiàn):
- protected Object createBean(String beanName, RootBeanDefinition
- mergedBeanDefinition, Object[] args)
- throws BeanCreationException {
- // Guarantee initialization of beans that the current one depends on.
- // 這里對(duì)取得當(dāng)前bean的所有依賴(lài)bean,確定能夠取得這些已經(jīng)被確定的bean,如果沒(méi)有被創(chuàng)建,那么這個(gè)createBean會(huì)被這些IOC
- // getbean時(shí)創(chuàng)建這些bean
- if (mergedBeanDefinition.getDependsOn() != null) {
- for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) {
- getBean(mergedBeanDefinition.getDependsOn()[i]);
- }
- }
- ........
- // 這里是實(shí)例化bean對(duì)象的地方,注意這個(gè)BeanWrapper類(lèi),是對(duì)bean操作的主要封裝類(lèi)
- if (instanceWrapper == null) {
- instanceWrapper = createBeanInstance(beanName, mergedBeanDefinition,args);
- }
- Object bean = instanceWrapper.getWrappedInstance();
- ......
- //這個(gè)populate方法,是對(duì)已經(jīng)創(chuàng)建的bean實(shí)例進(jìn)行依賴(lài)注入的地方,會(huì)使用到在loadBeanDefinition的時(shí)候得到的那些propertyValue來(lái)對(duì)bean進(jìn)行注入。
- if (continueWithPropertyPopulation) {
- populateBean(beanName, mergedBeanDefinition, instanceWrapper);
- }
- //這里完成客戶(hù)自定義的對(duì)bean的一些初始化動(dòng)作
- Object originalBean = bean;
- bean = initializeBean(beanName, bean, mergedBeanDefinition);
- // Register bean as disposable, and also as dependent on specified "dependsOn"beans.
- registerDisposableBeanIfNecessary(beanName, originalBean,mergedBeanDefinition);
- return bean;
- }
- .........
- }
這就是整個(gè)依賴(lài)注入的部分處理過(guò)程,在這個(gè)過(guò)程中起主要作用的是WrapperImp ,這個(gè)Wrapper不是一個(gè)簡(jiǎn)單的對(duì)bean對(duì)象的封裝,因?yàn)樗枰幚碓赽eanDefinition中的信息來(lái)迭代的處理依賴(lài)注入。
到這里,這是簡(jiǎn)單的,大概的對(duì)IOC和AOP進(jìn)行了解,入門(mén)先到這一點(diǎn)便已經(jīng)有了大概的印象了。
參考資料:《Spring_IOC詳解》
原文鏈接:http://blog.csdn.net/achan2090/article/details/7248043
【編輯推薦】
- Java多線程之消費(fèi)者生產(chǎn)者模式
- 深入理解Java對(duì)象序列化
- 對(duì)于Java類(lèi)加載過(guò)程中的順序問(wèn)題探究
- 菜鳥(niǎo)入門(mén)Java語(yǔ)言學(xué)習(xí)的要點(diǎn)
- Java自定義范型的應(yīng)用技巧