《java培訓(xùn)-Spring源碼閱讀入門指引》由會員分享,可在線閱讀,更多相關(guān)《java培訓(xùn)-Spring源碼閱讀入門指引(6頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、文檔供參考,可復(fù)制、編制,期待您的好評與關(guān)注!
Spring源碼閱讀入門指引
本文大概的對IOC和AOP進行了解,入門先到這一點便已經(jīng)有了大概的印象了,詳細內(nèi)容請看下文。
本文說明2點:
1.閱讀源碼的入口在哪里?
2.入門前必備知識了解:IOC和AOP
一、我們從哪里開始
1.準備工作:在官網(wǎng)上下載了Spring源代碼之后,導(dǎo)入Eclipse,以方便查詢。
2.打開我們使用Spring的項目工程,找到Web.xml這個網(wǎng)站系統(tǒng)配置文件,在其中找到Spring的初始化信息:
1. ?
2. ?org.sp
2、ringframework.web.context.ContextLoaderListener?
3. ?
由配置信息可知,我們開始的入口就這里ContextLoaderListener這個監(jiān)聽器。
在源代碼中我們找到了這個類,它的定義是:
1. public?class?ContextLoaderListener?extends?ContextLoader ?
2. ?implements?ServletContextListener?{ ?
3. ????… ?
4. ?/** ?
5. ??*?Initialize?
3、the?root?web?application?context. ?
6. ??*/?
7. ?public?void?contextInitialized(ServletContextEvent?event)?{ ?
8. ??this.contextLoader?=?createContextLoader(); ?
9. ??if?(this.contextLoader?==?null)?{ ?
10. ???this.contextLoader?=?this; ?
11. ??} ?
12. ??this.contextLoader.initWebApplicationC
4、ontext(event.getServletContext()); ?
13. ?} ?
14. ??... ?
15. } ?
該類繼續(xù)了ContextLoader并實現(xiàn)了監(jiān)聽器,關(guān)于Spring的信息載入配置、初始化便是從這里開始了,具體其他閱讀另外寫文章來深入了解。
二、關(guān)于IOC和AOP
關(guān)于Spring IOC 網(wǎng)上很多相關(guān)的文章可以閱讀,那么我們從中了解到的知識點是什么?
1)IOC容器和AOP切面依賴注入是Spring是核心。
IOC容器為開發(fā)者管理對象之間的依賴關(guān)系提供了便利和基礎(chǔ)服務(wù),其中Bean工廠(BeanFactory)和上下文(Application
5、Context)就是IOC的表現(xiàn)形式
BeanFactory是個接口類,只是對容器提供的最基本服務(wù)提供了定義,而DefaultListTableBeanFactory、XmlBeanFactory、ApplicationContext等都是具體的實現(xiàn)。
接口:
1. public?interface?BeanFactory?{ ?
2. ?//這里是對工廠Bean的轉(zhuǎn)義定義,因為如果使用bean的名字檢索IOC容器得到的對象是工廠Bean生成的對象, ?
3. ?//如果需要得到工廠Bean本身,需要使用轉(zhuǎn)義的名字來向IOC容器檢索 ?
4. ?String?FACTORY_BEA
6、N_PREFIX?=?"&"; ?
5. ?//這里根據(jù)bean的名字,在IOC容器中得到bean實例,這個IOC容器就象一個大的抽象工廠,用戶可以根據(jù)名字得到需要的bean ?
6. ?//在Spring中,Bean和普通的JAVA對象不同在于: ?
7. ?//Bean已經(jīng)包含了我們在Bean定義信息中的依賴關(guān)系的處理,同時Bean是已經(jīng)被放到IOC容器中進行管理了,有它自己的生命周期 ?
8. ?Object?getBean(String?name)?throws?BeansException; ?
9. ?//這里根據(jù)bean的名字和Class類型來得到bean實例,和上面的
7、方法不同在于它會拋出異常:如果根名字取得的bean實例的Class類型和需要的不同的話。 ?
10. ?Object?getBean(String?name,?Class?requiredType)?throws?BeansException; ?
11. ?//這里提供對bean的檢索,看看是否在IOC容器有這個名字的bean ?
12. ?boolean?containsBean(String?name); ?
13. ?//這里根據(jù)bean名字得到bean實例,并同時判斷這個bean是不是單件,在配置的時候,默認的Bean被配置成單件形式,如果不需要單件形式,需要用戶在Bean定
8、義信息中標注出來,這樣IOC容器在每次接受到用戶的getBean要求的時候,會生成一個新的Bean返回給客戶使用?-?這就是Prototype形式 ?
14. ?boolean?isSingleton(String?name)?throws?NoSuchBeanDefinitionException; ?
15. ?//這里對得到bean實例的Class類型 ?
16. ?Class?getType(String?name)?throws?NoSuchBeanDefinitionException; ?
17. ?//這里得到bean的別名,如果根據(jù)別名檢索,那么其原名也會被檢索出來
9、?
18. ?String[]?getAliases(String?name); ?
19. }?
實現(xiàn):
XmlBeanFactory的實現(xiàn)是這樣的:
1. public?class?XmlBeanFactory?extends?DefaultListableBeanFactory?{ ?
2. ?//這里為容器定義了一個默認使用的bean定義讀取器,在Spring的使用中,Bean定義信息的讀取是容器初始化的一部分,但是在實現(xiàn)上是和容器的注冊以及依賴的注入是分開的,這樣可以使用靈活的?bean定義讀取機制。 ?
3. ?private?final?XmlBeanDefinit
10、ionReader?reader?=?new?XmlBeanDefinitionReader(this); ?
4. ?//這里需要一個Resource類型的Bean定義信息,實際上的定位過程是由Resource的構(gòu)建過程來完成的。 ?
5. ?public?XmlBeanFactory(Resource?resource)?throws?BeansException?{ ?
6. ?this(resource,?null); ?
7. ?} ?
8. ?//在初始化函數(shù)中使用讀取器來對資源進行讀取,得到bean定義信息。這里完成整個IOC容器對Bean定義信息的載入和注冊過程 ?
11、
9. ?public?XmlBeanFactory(Resource?resource,?BeanFactory?parentBeanFactory)?throws?
10. ?BeansException?{ ?
11. ?super(parentBeanFactory); ?
12. ?this.reader.loadBeanDefinitions(resource); ?
13. }?
我們可以看到IOC容器使用的一些基本過程:
如:DefaultListableBeanFactory
1. ClassPathResource?res?=?new?ClassPathRes
12、ource("beans.xml");//讀取配置文件 ?
2. DefaultListableBeanFactory?factory?=?new?DefaultListableBeanFactory(); ?
3. XmlBeanDefinitionReader?reader?=?new?XmlBeanDefinitionReader(factory); ?
4. reader.loadBeanDefinitions(res); ?
這些代碼演示了以下幾個步驟:
1. 創(chuàng)建IOC配置文件的抽象資源
2. 創(chuàng)建一個BeanFactory,這里我們使用DefaultListableB
13、eanFactory;
3. 創(chuàng)建一個載入bean定義信息的讀取器,這里使用XmlBeanDefinitionReader來載入XML形式的bean定義信息,配置給BeanFactory;
4. 從定義好的資源位置讀入配置信息,具體的解析過程由XmlBeanDefinitionReader來完成,這樣完成整個載入和注冊bean定義的過程。我們的IoC容器就建立起來了。
再簡單的說,我的系統(tǒng)在啟動時候,會完成的動作就是:
1.由ResourceLoader獲取資源文件,也即bean的各種配置文件;
2.由BeanDefintion對配置文件的定義信息的載入;
3.用BeanDefin
14、itionRegistry接口來實現(xiàn)載入bean定義信息并向IOC容器進行注冊。
注意,IOC容器和上下文的初始化一般不包含Bean的依賴注入的實現(xiàn)。
2)AOP這個過程并不是在注冊bean的過程實現(xiàn)的。
我們只看到在處理相關(guān)的Bean屬性的時候,使用了RuntimeBeanReference對象作為依賴信息的紀錄。
在IOC容器已經(jīng)載入了用戶定義的Bean信息前提下,這個依賴注入的過程是用戶第一次向IOC容器索要Bean的時候觸發(fā)的,或者是我們可以在Bean定義信息中通過控制lazy-init屬性來使得容器完成對Bean的預(yù)實例化 - 這個預(yù)實例化也是一個完成依賴注入的過程。
我們
15、說明一下過程:
1.用戶想IOC容器請求Bean。
2.系統(tǒng)先在緩存中查找是否有該名稱的Bean(去各個BeanFactory去查找)
3.沒有的話就去創(chuàng)建Bean并進行依賴注入,并且這個請求將被記錄起來。
請求Bean具體的實現(xiàn):
代碼入口在DefaultListableBeanFactory的基類AbstractBeanFactory中:
1. public?Object?getBean(String?name,?Class?requiredType,?final?Object[]?args)?throwsBeansException?{ ?
2. ... ?
3. ?Ob
16、ject?sharedInstance?=?getSingleton(beanName);//先去緩存取 ?
4. ?if?(sharedInstance?!=?null)?{ ?
5. ?... ?
6. ??if?(containsBeanDefinition(beanName))?{ ?
7. ???RootBeanDefinition?mergedBeanDefinition?=?getMergedBeanDefinition(beanName,?false); ?
8. ???bean?=?getObjectForBeanInstance(sharedInstance,?n
17、ame,mergedBeanDefinition); ?
9. ??} ?
10. ??else?{ ?
11. ???bean?=?getObjectForBeanInstance(sharedInstance,?name,?null); ?
12. ??} ?
13. ?} ?
14. ?else?{ ?
15. ? ?
16. ?} ?
17. ?
18. ... ?
19. }?
注入Bean具體的實現(xiàn):
具體的bean創(chuàng)建過程和依賴關(guān)系的注入在createBean中,這個方法在AbstractAutowireCapableBeanFactory中給出了實現(xiàn):
18、
1. protected?Object?createBean(String?beanName,?RootBeanDefinition ?
2. mergedBeanDefinition,?Object[]?args) ?
3. throws?BeanCreationException?{ ?
4. ?//?Guarantee?initialization?of?beans?that?the?current?one?depends?on. ?
5. ?//?這里對取得當前bean的所有依賴bean,確定能夠取得這些已經(jīng)被確定的bean,如果沒有被創(chuàng)建,那么這個createBean會被
19、這些IOC ?
6. ?//?getbean時創(chuàng)建這些bean ?
7. ?if?(mergedBeanDefinition.getDependsOn()?!=?null)?{ ?
8. ??for?(int?i?=?0;?i?
20、nWrapper類,是對bean操作的主要封裝類 ?
14. ?if?(instanceWrapper?==?null)?{ ?
15. ??instanceWrapper?=?createBeanInstance(beanName,?mergedBeanDefinition,args); ?
16. ?} ?
17. ?Object?bean?=?instanceWrapper.getWrappedInstance(); ?
18. ?...... ?
19. ?//這個populate方法,是對已經(jīng)創(chuàng)建的bean實例進行依賴注入的地方,會使用到在loadBeanDefiniti
21、on的時候得到的那些propertyValue來對bean進行注入。 ?
20. ?if?(continueWithPropertyPopulation)?{ ?
21. ??populateBean(beanName,?mergedBeanDefinition,?instanceWrapper); ?
22. ?} ?
23. ?//這里完成客戶自定義的對bean的一些初始化動作 ?
24. ?Object?originalBean?=?bean; ?
25. ?bean?=?initializeBean(beanName,?bean,?mergedBeanDefinition)
22、; ?
26. ?//?Register?bean?as?disposable,?and?also?as?dependent?on?specified?"dependsOn"beans. ?
27. ?registerDisposableBeanIfNecessary(beanName,?originalBean,mergedBeanDefinition); ?
28. ?return?bean; ?
29. } ?
30. ......... ?
31. }?
這就是整個依賴注入的部分處理過程,在這個過程中起主要作用的是WrapperImp ,這個Wrapper不是一個簡單的對bean對象的封裝,因為它需要處理在beanDefinition中的信息來迭代的處理依賴注入。
到這里,這是簡單的,大概的對IOC和AOP進行了解,入門先到這一點便已經(jīng)有了大概的印象了。
參考資料:《Spring_IOC詳解》
原文鏈接:中軟卓越
6 / 6