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