導航:首頁 > 源碼編譯 > spring源碼記不住

spring源碼記不住

發布時間:2023-11-29 14:10:44

㈠ 詳解Spring mvc工作原理及源碼分析

Model 模型層 (javaBean組件 = 領域模型(javaBean) + 業務層 + 持久層)

View 視圖層( html、jsp…)

Controller 控制層(委託模型層進行數據處理)

springmvc是一個web層mvc框架,類似struts2。

springmvc是spring的部分,其實就是spring在原有基礎上,又提供了web應用的mvc模塊。

實現機制:

struts2是基於過濾器實現的。

springmvc是基於servlet實現的。

運行速度:

因為過濾器底層是servlet,所以springmvc的運行速度會稍微比structs2快。

struts2是多例的

springmvc單例的

參數封裝:

struts2參數封裝是基於屬性進行封裝。

springmvc是基於方法封裝。顆粒度更細。

⑴ 用戶發送請求至DispatcherServlet。

⑵ DispatcherServlet收到請求調用HandlerMapping查詢具體的Handler。

⑶ HandlerMapping找到具體的處理器(具體配置的是哪個處理器的實現類),生成處理器對象及處理器攔截器(HandlerExcutorChain包含了Handler以及攔截器集合)返回給DispatcherServlet。

⑷ DispatcherServlet接收到HandlerMapping返回的HandlerExcutorChain後,調用HandlerAdapter請求執行具體的Handler(Controller)。

⑸ HandlerAdapter經過適配調用具體的Handler(Controller即後端控制器)。

⑹ Controller執行完成返回ModelAndView(其中包含邏輯視圖和數據)給HandlerAdaptor。

⑺ HandlerAdaptor再將ModelAndView返回給DispatcherServlet。

⑻ DispatcherServlet請求視圖解析器ViewReslover解析ModelAndView。

⑼ ViewReslover解析後返回具體View(物理視圖)到DispatcherServlet。

⑽ DispatcherServlet請求渲染視圖(即將模型數據填充至視圖中) 根據View進行渲染視圖。

⑾ 將渲染後的視圖返回給DispatcherServlet。

⑿ DispatcherServlet將響應結果返回給用戶。

(1)前端控制器DispatcherServlet(配置即可)

功能:中央處理器,接收請求,自己不做任何處理,而是將請求發送給其他組件進行處理。DispatcherServlet 是整個流程的控制中心。

(2)處理器映射器HandlerMapping(配置即可)

功能:根據DispatcherServlet發送的url請求路徑查找Handler

常見的處理器映射器:BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping,

,(不建議使用)

(3)處理器適配器HandlerAdapter(配置即可)

功能:按照特定規則(HandlerAdapter要求的規則)去執行Handler。

通過HandlerAdapter對處理器進行執行,這是適配器模式的應用,通過擴展多個適配器對更多類型的處理器進行執行。

常見的處理器適配器:HttpRequestHandlerAdapter,,

(4)處理器Handler即Controller(程序猿編寫)

功能:編寫Handler時按照HandlerAdapter的要求去做,這樣適配器才可以去正確執行Handler。

(5)視圖解析器ViewReslover(配置即可)

功能:進行視圖解析,根據邏輯視圖名解析成真正的視圖。

ViewResolver負責將處理結果生成View視圖,ViewResolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最後對View進行渲染將處理結果通過頁面展示給用戶。

springmvc框架提供了多種View視圖類型,如:jstlView、freemarkerView、pdfView...

(6)視圖View(程序猿編寫)

View是一個介面,實現類支持不同的View類型(jsp、freemarker、pdf...)

引入相關依賴:spring的基本包、springmvc需要的spring-webmvc,日誌相關的slf4j-log4j12,jsp相關的jstl、servlet-api、jsp-api。

因為DispatcherServlet本身就是一個Servlet,所以需要在web.xml配置。

一、使用默認載入springmvc配置文件的方式,必須按照以下規范:

①命名規則:-servlet.xml ====> springmvc-servlet.xml

②路徑規則:-servlet.xml必須放在WEB-INF下邊

二、如果要不按照默認載入位置,則需要在web.xml中通過標簽來指定springmvc配置文件的載入路徑,如上圖所示。

將自定義的 Controller 處理器配置到 spring 容器中交由 spring 容器來管理,因為這里的 springmvc.xml 配置文件中處理器映射器配置的是 BeanNameUrlHandlerMapping ,根據名字可知這個處理器映射器是根據 bean (自定義Controller) 的 name 屬性值url去尋找執行類 Handler(Controller) , 所以bean的name屬性值即是要和用戶發送的請求路徑匹配的 url 。

根據視圖解析路徑:WEB-INF/jsps/index.jsp

功能:根據bean(自定義Controller)的name屬性的url去尋找執行類Controller。

功能:自定義的處理器(Controller)實現了Controller介面時,適配器就會執行Controller的具體方法。

會自動判斷自定義的處理器(Controller)是否實現了Controller介面,如果是,它將會自動調用處理器的handleRequest方法。

Controller介面中有一個方法叫handleRequest,也就是處理器方法。

因此,自定義的Controller要想被調用就必須實現Controller介面,重寫Controller介面中的處理器方法。

㈡ 學習JAVA的同學都是怎麼讀源碼的

剛參加工作那會,沒想過去讀源碼,更沒想過去改框架的源碼;總想著別人的框架應該是完美的、萬能的,應該不需要改;另外即使我改了源碼,怎麼樣讓我的改動生效了?項目中引用的不還是沒改的jar包嗎。回想起來覺得那時候的想法確實挺??

工作了一年多之後准備跳槽了,開始了一輪的面試,其中有幾個面試官就問到了相關的源碼問題:ArrayList、HashMap的底層實現,spring、mybatis的相關源碼。問源碼的面試一般就是回去等消息,然後就沒然後了。

那時候開始意識到,源碼這東西在之前的工作的中感受不到,但是在面試中好像面的還挺頻繁的,從此有意識的開始了jdk部分源碼的閱讀(主要是集合)。一開始看源碼,看的特別糙,知道個大概,知道ArrayList的底層實現是數組,HashMap的底層是散列表(數組+鏈表);更深入一點的擴容、hash碰撞等等就不知道了。

讀spring源碼起於工作中遇到了一個問題(springjdbcTemplate事務,各種詭異,包你醍醐灌頂!),排查一段時間最終是解決了,但過程讓我非常難受,各種上網查資料、各種嘗試,感覺就像大海撈針一樣,遙遙無期。我下定決心,我要看一看spring的源碼,於是我買了一本《spring源碼深度斗帶解析》,結合著這本書、打開著eclipse,開始了spring的源碼閱讀之旅。至此,讀源碼成了習慣,源碼已經進入了我的心裡。

後來,springboot的火熱,讓我也想蹭上一蹭,於是有了springboot的啟動源碼系列,雖然還在進行中,指侍但是我相信我能將其完成;工作中用到了shiro,我又結合著《跟我學shiro》將shiro的源碼看了個大概,有了shiro源碼系列博文,還差一篇認證與授權(應該很快就能面世),shiro源碼系列就封筆了。最近在搭建自己的後台管理系統,用到了quartz,集成的過程也遇到了一些問題,因此有了quartz的兩篇文章。

慢慢的,從一味的網上找資料變成了很多時候會從源碼中找答案。不求能讀太多的源碼,但願自己接觸的技術都能讀上一讀,路漫漫其修遠兮,吾將上下而求索!

大家為什麼要讀源碼?

很多人一定和我一樣的感受:源碼在工作中有用嗎?用處大嗎?很長一段時間內我也有這樣的疑問,認為哪些有事沒事扯源碼的人就是在裝,只是為了提高他們的逼格而已。

那為什麼我還要讀源碼呢?一剛開始為了面試,後來為了解決工作中的問題,再後來就是個人喜好了。說的好聽點是有匠人精神;說的委婉點是好奇(底層是怎麼實現的);說的不自信點是對黑盒的東西我用的沒底,怕用錯;說的簡單直白點是提升自我價值,為了更高的薪資待遇(這里對真正的技術迷說聲抱歉)。

源碼中我們可以學到很多東西,學習別人高效的代碼書寫、學習別人對設計模式的熟練使用、學習別人對整個架構的布局,等等。如果你還能找出其中的不足,那麼恭喜你,你要飛升了!會使用固然重要,但知道為什麼這么使用同樣重要。從模仿中學習,從模仿中創新。

讀源碼不像圍城(外面的人想進來,裡面的人想出去),它是外面的人不想進來,裡面的人不想出去;當我們跨進城內,你會發現(還是城外好,皮!)城內風光無限,源碼的海洋任我們遨遊!

首先我們要對我們的目標有所了解,知道她有什麼特點,有些什麼功能。對對方都還不了解,就想著進入別人的內心世界,那不是臭不要臉嘛,我們要做一個有著流氓心的紳士;對她有個大致的了解了,就可以發起攻勢,一舉拿下。

那麼怎麼樣了解了,方式有很多,我這里提供幾種,僅供參考

最好的方式就是官方參考指南,親生父母往往對孩子是最了解的,對孩子的描述也是最詳細的;比唯銷吵如SpringBootReferenceGuide就是對springboot最詳細的描述,怎麼樣使用springboot、springboot特性等等,通過此指南,springboot在你面前一覽無遺;

但是,springboot畢竟是外國人的孩子,如果英語不好,估計讀起來有點頭疼了,不過我們有google翻譯呀,咬咬牙也是能看的。源碼世界的丈母娘、老岳丈是非常慷慨的!

其次是書籍,國外優秀的有很多,國內也不乏好書,比較推薦此方式,自成體系,讓我們掌握的知識點不至於太散。這就是好比是源碼的閨蜜,對源碼非常了解,重點是挺大方,會盡全力幫助我們了解源碼。

再次就是博客,雖然可能覺得知識點比較散,但是針對某個知識點卻特別的細,對徹底掌握非常有幫助,園子內就有很多技術大牛,寫的博客自然也是非常棒,非常具有學習價值。當然還有社區、論壇、github、碼雲等等。這就是源碼的朋友圈,我們從中也能獲取到非常多關於源碼的信息。

設計模式的了解

優秀的框架、技術從不乏設計模式;jdk源碼中就應用了很多設計模式,比如IO流中的適配器模式與裝飾模式、GUI的觀察者模式、集合中的迭代器模式等等;spring源碼中也是用到了大量的設計模式。設計模式有什麼優點、各適用於什麼場景,不是本文的內容,需要我們大家自行去了解。

我們只需要對一些常用的設計模式有個大致了解,再去讀源碼是比較好的;不需要將23種設計模式都通讀,也不需要將常用設計模式完全理解透;對於全部通讀,我們時間有限,另外有些模式確實不太好理解、用的少,性價比不高,沒必要全部都讀。

推薦書籍:《HeadFirstDesignPatterns》(中文版:《HeadFirst設計模式》)、《Java與模式》;

另外我比較推薦的一種學習設計模式的方式是讀別人博客:java_my_life,劉偉技術博客,chenssy的設計模式;

設計模式之於源碼,就好比逛街購物之於女人,想順利勾搭源碼,我們需要好好掌握設計模式這個套路。

配合ide進行斷點追蹤

我們通過源碼的圈子對源碼的了解終究只是停在表面,終究還是沒有走進她的內心,接下來我就和大家分享下,我是如何走進她的內心的!

相信看過我的源碼博客的小夥伴都知道,我非常喜歡通過idea斷點來進行源碼追蹤,斷點追蹤源碼是我非常推薦的一種方式。斷點不僅可以用來調試我們的代碼,也可以用來調試我們用到的框架源碼。

面對未知的、茫茫多的源碼,我們往往沒有足夠的時間、經歷和耐心去通讀所有源碼,我們只需要去讀我們關注的部分即可(有人可能會說我都不關心,這?)。那為什麼要用斷掉調試的方式來跟源碼,而不是直接從源代碼入手去跟我們關注的部分呢?

嘗試過的小夥伴應該知道,如果我們對源碼不熟悉,直接通過源碼的方式去跟,一方面很容易迷路(多態,會有很多子類實現),不知道接下來跟哪一個,另一方面也很容易跟丟,當我們跟入的很深的時候,很有可能就忘記上一步跟到哪了。所以讀源碼的重要性淺顯易懂了。

㈢ [Spring boot源碼解析] 2 啟動流程分析

在了解 Spring Boot 的啟動流程的時候,我們先看一下一個Spring Boot 應用是如何啟動的,如下是一個簡單的 SpringBoot 程序,非常的簡潔,他是如何做到的呢,我們接下來就將一步步分解。

我們追蹤 SpringApplication.run() 方法,其實最終它主要的邏輯是新建一個 SpringApplication ,然後調用他的 run 方法,如下:

我們先來看一下創建 SpringApplication 的方法:

在將Main class 設置 primarySources 後,調用了 WebApplicationType.deceFromClasspath() 方法,該方法是為了檢查當前的應用類型,並設置給 webApplicationType 。 我們進入 deceFromClasspath 方法 :

這里主要是通過類載入器判斷是否存在 REACTIVE 相關的類信息,假如有就代表是一個 REACTIVE 的應用,假如不是就檢查是否存在 Servelt 和 ,假如都沒有,就代表應用為非 WEB 類應用,返回 NONE ,默認返回 SERVLET 類型,我們這期以我們目前最常使用的 SERVLET 類型進行講解,所以我們在應用中引入了 spring-boot-starter-web 作為依賴:

他會包含 Spring-mvc 的依賴,所以就包含了內嵌 tomcat 中的 Servlet 和 Spring-web 中的 ,因此返回了 SERVLET 類型。

回到剛才創建 SpringApplication 的構建方法中,我們設置完成應用類型後,就尋找所有的 Initializer 實現類,並設置到 SpringApplication 的 Initializers 中,這里先說一下 getSpringFactoriesInstances 方法,我們知道在我們使用 SpringBoot 程序中,會經常在 META-INF/spring.factories 目錄下看到一些 EnableAutoConfiguration ,來出發 config 類注入到容器中,我們知道一般一個 config 類要想被 SpringBoot 掃描到需要使用 @CompnentScan 來掃描具體的路徑,對於 jar 包來說這無疑是非常不方便的,所以 SpringBoot 提供了另外一種方式來實現,就是使用 spring.factories ,比如下面這個,我們從 Springboot-test 中找到的例子,這里先定義了一個ExampleAutoConfiguration,並加上了 Configuration 註解:

然後在 spring.factories 中定義如下:

那這種方式是怎麼實現的你,這就要回到我們剛才的方法 getSpringFactoriesInstances :

我們先來看一下傳入參數,這里需要注意的是 args,這個是初始化對應 type 的時候傳入的構造參數,我們先看一下 SpringFactoriesLoader#loadFactoryNames 方法:

首先是會先檢查緩存,假如緩存中存在就直接返回,假如沒有就調用 classLoader#getResources 方法,傳入 META-INF/spring.factories ,即獲取所有 jar 包下的對應文件,並封裝成 UrlResource ,然後使用 PropertiesLoaderUtils 將這些信息讀取成一個對一對的 properties,我們觀察一下 spring.factories 都是按 properties 格式排版的,假如有多個就用逗號隔開,所以這里還需要將逗號的多個類分隔開來,並加到 result 中,由於 result 是一個 LinkedMultiValueMap 類型,支持多個值插入,最後放回緩存中。最終完成載入 META-INF/spring.factories 中的配置,如下:

我們可以看一下我們找到的 initializer 有多少個:

在獲取到所有的 Initializer 後接下來是調用 方法進行初始化。

這里的 names 就是我們上面通過類載入器載入到的類名,到這里會先通過反射生成 class 對象,然後判斷該類是否繼承與 ApplicationContextInitializer ,最後通過發射的方式獲取這個類的構造方法,並調用該構造方法,傳入已經定義好的構造參數,對於 ApplicationContextInitializer 是無參的構造方法,然後初始化實例並返回,回到原來的方法,這里會先對所有的 ApplicationContextInitializer 進行排序,調用 #sort(instances) 方法,這里就是根據 @Order 中的順序進行排序。

接下來是設置 ApplicationListener ,我們跟進去就會發現這里和上面獲取 ApplicationContextInitializer 的方法如出一轍,最終會載入到如圖的 15 個 listener (這里除了 外,其他都是 SpringBoot 內部的 Listener):

在完成 SpringApplication 對象的初始化後,我們進入了他的 run 方法,這個方法幾乎涵蓋了 SpringBoot 生命周期的所有內容,主要分為九個步驟,每一個步驟這里都使用註解進行標識:

主要步驟如下:
第一步:獲取 SpringApplicationRunListener, 然後調用他的 staring 方法啟動監聽器。
第二步:根據 SpringApplicationRunListeners以及參數來准備環境。
第三步:創建 Spring 容器。
第四步:Spring 容器的前置處理。
第五步:刷新 Spring 容器。
第六步: Spring 容器的後置處理器。
第七步:通知所有 listener 結束啟動。
第八步:調用所有 runner 的 run 方法。
第九步:通知所有 listener running 事件。
我們接下來一一講解這些內容。

我們首先看一下第一步,獲取 SpringApplicationRunListener :

這里和上面獲取 initializer 和 listener 的方式基本一致,都是通過 getSpringFactoriesInstances , 最終只找到一個類就是: org.springframework.boot.context.event.EventPublishingRunListener ,然後調用其構造方法並傳入產生 args , 和 SpringApplication 本身:

我們先看一下構造函數,首先將我們獲取到的 ApplicationListener 集合添加到initialMulticaster 中, 最後都是通過操作 來進行廣播,我,他繼承於 ,我們先看一下他的 addApplicationListener 方法:

我們可以看出,最後是放到了 applicationListenters 這個容器中。他是 defaultRetriever 的成員屬性, defaultRetriever 則是 的私有類,我們簡單看一下這個類:

我們只需要看一下這里的 getApplicationListeners 方法,它主要是到 beanFactory 中檢查是否存在多的 ApplicationListener 和舊的 applicationListeners 組合並返回,接著執行 listener 的 start 方法,最後也是調用了 的 multicastEvent 查找支持對應的 ApplicationEvent 類型的通知的 ApplicationListener 的 onApplicationEvent 方法 ,這里除了會:

篩選的方法如下,都是調用了對應類型的 supportsEventType 方法 :

如圖,我們可以看到對 org.springframework.boot.context.event.ApplicationStartingEvent 感興趣的有5個 Listener

環境准備的具體方法如下:

首先是調用 getOrCreateEnvironment 方法來創建 environment ,我們跟進去可以發現這里是根據我們上面設置的環境的類型來進行選擇的,當前環境會創建 StandardServletEnvironment

我們先來看一下 StandardServletEnvironment 的類繼承關系圖,我們可以看出他是繼承了 AbstractEnvironment :

他會調用子類的 customizePropertySources 方法實現,首先是 StandardServletEnvironment 的實現如下,他會添加 servletConfigInitParams , servletContextInitParams , jndiProperties 三種 properties,當前調試環境沒有配置 jndi properties,所以這里不會添加。接著調用父類的 customizePropertySources 方法,即調用到了 StandardEnvironment 。

我們看一下 StandardEnvironment#customizePropertySources 方法,與上面的三個 properties 創建不同,這兩個是會進行賦值的,包括系統環境變數放入 systemEnvironment 中,jvm 先關參數放到 systemProperties 中:

這里會添加 systemEnvironment 和 systemProperties 這兩個 properties,最終拿到的 properties 數量如下 4個:

在創建完成 Environment 後,接下來就到了調用 configureEnvironment 方法:

我們先看一下 configurePropertySources 方法,這里主要分兩部分,首先是查詢當前是否存在 defaultProperties ,假如不為空就會添加到 environment 的 propertySources 中,接著是處理命令行參數,將命令行參數作為一個 CompositePropertySource 或則 添加到 environment 的 propertySources 裡面,

接著調用 ConfigurationPropertySources#attach 方法,他會先去 environment 中查找 configurationProperties , 假如尋找到了,先檢查 configurationProperties 和當前 environment 是否匹配,假如不相等,就先去除,最後添加 configurationProperties 並將其 sources 屬性設置進去。

回到我們的 prepareEnvironment 邏輯,下一步是通知觀察者,發送 事件,調用的是 SpringApplicationRunListeners#environmentPrepared 方法,最終回到了 #multicastEvent 方法,我們通過 debug 找到最後對這個時間感興趣的 Listener 如下:

其主要邏輯如下:

這個方法最後載入了 PropertySourceLoader , 這里主要是兩種,一個是用於 Properties 的,一個是用於 YAML 的如下:

其中 apply 方法主要是載入 defaultProperties ,假如已經存在,就進行替換,而替換的目標 PropertySource 就是 load 這里最後的一個 consumer 函數載入出來的,這里列一下主要做的事情:
1、載入系統中設置的所有的 Profile 。
2、遍歷所有的 Profile ,假如是默認的 Profile , 就將這個 Profile 加到 environment 中。
3、調用load 方法,載入配置,我們深入看一下這個方法:

他會先調用 getSearchLocations 方法,載入所有的需要載入的路徑,最終有如下路徑:

其核心方法是遍歷所有的 propertySourceLoader ,也就是上面載入到兩種 propertySourceLoader ,最紅 loadForFileExtension 方法,載入配置文件,這里就不展開分析了,說一下主要的作用,因為每個 propertySourceLoader 都有自己可以載入的擴展名,默認擴展名有如下四個 properties, xml, yml, yaml,所以最終拿到文件名字,然後通過 - 拼接所有的真實的名字,然後加上路徑一起載入。

接下來,我們分析 BackgroundPreinitializer ,這個方法在接收 ApplicationPrepareEnvironment 事件的時候真正調用了這份方法:

1、 ConversionServiceInitializer 主要負責將包括 日期,貨幣等一些默認的轉換器注冊到 formatterRegistry 中。
2、 ValidationInitializer 創建 validation 的匹配器。
3、 MessageConverterInitializer 主要是添加了一些 http 的 Message Converter。
4、 JacksonInitializer 主要用於生成 xml 轉換器的。
接著回到我們將的主體方法, prepareEnvironment 在調用完成 listeners.environmentPrepared(environment) 方法後,調用 bindToSpringApplication(environment) 方法,將 environment 綁定到 SpirngApplication 中。
接著將 enviroment 轉化為 StandardEnvironment 對象。
最後將 configurationProperties 加入到 enviroment 中, configurationProperties 其實是將 environment 中其他的 PropertySource 重新包裝了一遍,並放到 environment 中,這里主要的作用是方便 進行解析。

它主要是檢查是否存在 spring.beaninfo.ignore 配置,這個配置的主要作用是設置 javaBean 的內省模式,所謂內省就是應用程序在 Runtime 的時候能檢查對象類型的能力,通常也可以稱作運行時類型檢查,區別於反射主要用於修改類屬性,內省主要用戶獲取類屬性。那麼我們什麼時候會使用到內省呢,java主要是通過內省工具 Introspector 來完成內省的工作,內省的結果通過一個 Beaninfo 對象返回,主要包括類的一些相關信息,而在 Spring中,主要是 BeanUtils#Properties 會使用到,Spring 對內省機制還進行了改進,有三種內省模式,如下圖中紅色框框的內容,默認情況下是使用 USE_ALL_BEANINFO。假如設置為true,就是改成第三中 IGNORE_ALL_BEANINFO

首先是檢查 Application的類型,然後獲取對應的 ApplicationContext 類,我們這里是獲取到了 org.springframework.boot.web.servlet.context. 接著調用 BeanUtils.instantiateClass(contextClass); 方法進行對象的初始化。

最終其實是調用了 的默認構造方法。我們看一下這個方法做了什麼事情。這里只是簡單的設置了一個 reader 和一個 scanner,作用於 bean 的掃描工作。

我們再來看一下這個類的繼承關系

這里獲取 ExceptionReporter 的方式主要還是和之前 Listener 的方式一致,通過 getSpringFactoriesInstances 來獲取所有的 SpringBootExceptionReporter 。

其主要方法執行如下:

㈣ 如何查看spring源碼

1.准備工作:在官網上下載了Spring源代碼之後,導入Eclipse,以方便查詢。
2.打開我們使用Spring的項目工程,找到Web.xml這個網站系統配置文件,在其中找到Spring的初始化信息:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

由配置信息可知,我們開始的入口就這里ContextLoaderListener這個監聽器。
在源代碼中我們找到了這個類,它的定義是:
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());
}
...
}

該類繼續了ContextLoader並實現了監聽器,關於Spring的信息載入配置、初始化便是從這里開始了,具體其他閱讀另外寫文章來深入了解。
二、關於IOC和AOP
關於Spring IOC 網上很多相關的文章可以閱讀,那麼我們從中了解到的知識點是什麼?
1)IOC容器和AOP切面依賴注入是Spring是核心。
IOC容器為開發者管理對象之間的依賴關系提供了便利和基礎服務,其中Bean工廠(BeanFactory)和上下文(ApplicationContext)就是IOC的表現形式。BeanFactory是個介面類,只是對容器提供的最基本服務提供了定義,而DefaultListTableBeanFactory、XmlBeanFactory、ApplicationContext等都是具體的實現。
介面:

public interface BeanFactory {
//這里是對工廠Bean的轉義定義,因為如果使用bean的名字檢索IOC容器得到的對象是工廠Bean生成的對象,
//如果需要得到工廠Bean本身,需要使用轉義的名字來向IOC容器檢索
String FACTORY_BEAN_PREFIX = "&";
//這里根據bean的名字,在IOC容器中得到bean實例,這個IOC容器就象一個大的抽象工廠,用戶可以根據名字得到需要的bean
//在Spring中,Bean和普通的JAVA對象不同在於:
//Bean已經包含了我們在Bean定義信息中的依賴關系的處理,同時Bean是已經被放到IOC容器中進行管理了,有它自己的生命周期
Object getBean(String name) throws BeansException;
//這里根據bean的名字和Class類型來得到bean實例,和上面的方法不同在於它會拋出異常:如果根名字取得的bean實例的Class類型和需要的不同的話。
Object getBean(String name, Class requiredType) throws BeansException;
//這里提供對bean的檢索,看看是否在IOC容器有這個名字的bean
boolean containsBean(String name);
//這里根據bean名字得到bean實例,並同時判斷這個bean是不是單件,在配置的時候,默認的Bean被配置成單件形式,如果不需要單件形式,需要用戶在Bean定義信息中標注出來,這樣IOC容器在每次接受到用戶的getBean要求的時候,會生成一個新的Bean返回給客戶使用 - 這就是Prototype形式
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//這里對得到bean實例的Class類型
Class getType(String name) throws NoSuchBeanDefinitionException;
//這里得到bean的別名,如果根據別名檢索,那麼其原名也會被檢索出來
String[] getAliases(String name);
}

實現:
XmlBeanFactory的實現是這樣的:
public class XmlBeanFactory extends DefaultListableBeanFactory {
//這里為容器定義了一個默認使用的bean定義讀取器,在Spring的使用中,Bean定義信息的讀取是容器初始化的一部分,但是在實現上是和容器的注冊以及依賴的注入是分開的,這樣可以使用靈活的 bean定義讀取機制。
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
//這里需要一個Resource類型的Bean定義信息,實際上的定位過程是由Resource的構建過程來完成的。
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
//在初始化函數中使用讀取器來對資源進行讀取,得到bean定義信息。這里完成整個IOC容器對Bean定義信息的載入和注冊過程
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws
BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}

閱讀全文

與spring源碼記不住相關的資料

熱點內容
華三交換機保存命令 瀏覽:597
命令方塊怎麼調鍵盤 瀏覽:841
不把密碼存在伺服器上怎麼辦 瀏覽:398
怎麼讓指令方塊的命令消失 瀏覽:543
用單片機做plc 瀏覽:404
雲伺服器進入子目錄命令 瀏覽:795
伺服器機櫃如何配電 瀏覽:578
怎麼刪除iphone資源庫里的app 瀏覽:940
pdf魚 瀏覽:648
單片機pcf8591什麼作用 瀏覽:805
sql命令學院 瀏覽:283
加密軟體在電腦那個盤 瀏覽:988
android獲取外部存儲 瀏覽:573
怎麼查自己家的伺服器地址 瀏覽:858
編程c語言工作好不好 瀏覽:569
單片機焊接地怎麼連接 瀏覽:694
游戲源碼怎麼抓 瀏覽:216
程序員幫大家引走怪物 瀏覽:16
手機網頁小游戲源碼 瀏覽:513
戰地一伺服器怎麼設置管理員 瀏覽:396