spring源碼深度解析
『壹』 大家能給推薦幾本學習java的書籍吧
如果不是初學者 進階階段 Java Cook Book》- 非常推薦* (包含了Java編程的Tips,適合當做手冊來查閱) 《O』reilly-Java IO》- 推薦* (包含Java IO編程的各個方面) 《O』reilly-Database Programming with JDBC》- 推薦* (JDBC編程) 《O』reilly-Java Programming with Oracle JDBC》- 參考* 進一步深造可供選擇Java Web編程 《O』reilly-Java Server Pages》- 強烈推薦* 《O』reilly-Java Servlet Programming》- 非常推薦* 《O』reilly-Jakarta Struts》- 推薦* (Java Web編程的一個MVC實現框架Struts的書) EJB編程 《J2EE應用與BEA Weblogic Server》- 強烈推薦 《Mastering EJB 2.0》- 非常推薦* 《Enterprise Java Bean》- 推薦* Java XML編程 《O』reilly-Java and XML》- 推薦* 《O』reilly-Java and SOAP》- 參考* (Java的SOAP編程) 設計模式 《Core J2EE Patterns》- 強烈推薦* (J2EE設計模式,設計企業應用軟體必備參考書) 《EJB Design Patterns》- 推薦* 其它 《O』reilly Ant - The Definitive Guide》- 推薦* (Ant是一種功能非常強大的Java工具)
『貳』 spring源碼怎麼讀
在我們的生活之中,有形形色色的萬物(Object),有飛機,有汽車,有輪船,還有我這個滄海一粟的java講師。
試問:了解飛機底層架構的人,就一定能把飛機開好嗎?精通汽車的構造和底層原理的人,就保證開車不出事故嗎?或者反過來問,一個多年的開計程車的老司機,技術非常嫻熟,但是你問他汽車的架構和底層原理,你覺得有多少老司機能准確的答出來?
那就對了,了解了,讀懂了spring底層源碼的程序員,我們並不能保證他就是一個好程序員,我心中的一個好的程序員是要能夠提出解決方案的程序員,就好比清華北大確實只是個過程,最後的目的,是為國家為人民做出奉獻才是我們活著的價值。所以說我並不看好去閱讀spring源碼這個行為。聞道有先後,術業有專攻,我們不是提供底層技術的人!絕大多數的程序員,我以為正確的做法是站在巨人的肩膀上,把前輩留下來的精髓發揚光大才是正道,簡而言之,把怎麼用,和為什麼要這么用學好才是大多數程序員學習技術的關鍵。就好比去學駕照的時候,教練只需要關心你是否會開車,是否遵守交通規則,並不關心你是否了解汽車是如何在路上跑起來的。
一個人的精力和時間都是有限的,分細了來說,開發者就是技術的使用者,重點在於如何正確熟練的使用,而不是一昧地去關心底層原理,如果要完全讀懂spring源碼,首先,英語就得很厲害吧,其次,得花多少時間?就算讀懂了,那收獲和付出也不成正比,大把大把的時間為何不花在java更多,更高級,更有意義的技術上呢?筆者此話並不是說spring源碼讀了沒用,只是讓我們的時間更有價值,例如分布式微服務,區塊鏈技術,大數據,python,作為新時代的IT佼佼者,我們是否應該隨著時代的腳步,迎接嶄新的未來?我奉勸大多數人,不必去看spring源碼,除非你確實感興趣作為技術研究,這樣是可以的。一個正常的工作者,是不建議花寶貴的時間去看的,那學生就更不應該去看了。此話怎講?我以為,學生應以學業為重,士不可不弘毅,任重而道遠,首先應該擴展其知識的廣度,和技術的嫻熟使用,再培養學生獨立解決問題的能力,溝通協作的能力,最後才考慮技術的深度。
筆者在多年前也被面試過很多很多問題,但是從來沒有一個面試官會問spring底層源碼,曾經阿里巴巴的架構師也面試過我,直到後來,我成為了面試官,當我去面試別人的時候,我也不會去問spring源碼這些東西,因為99.9%企業招人進來,是要做事實的,不是讓你去研究一個技術,絕大多數更在乎的是利用現有的技術,去完成一些項目功能。除了世界上極少數著名的企業他們需要技術研究員,才對這些有所要求,那要招這類人才,估計至少也是名校研究生以上吧,所以普通程序開發者,我覺得學好技術的正確與熟練使用,才是重中之重!
不宜本末倒置,不宜好高騖遠。筆者從事Java行業以來,真要說全階段全程全棧都精通的人,應屬風毛菱角,故此,更應讓所學知識運籌帷幄,舉一反三,千里爐火,萬里純青。以上篇幅在說我對閱讀spring源碼的一些強烈建議,最終結論,是不看、不讀就此作罷。
那有的感興趣的人非要閱讀呢?
Ok,其實閱讀spring源碼並不算很難。
首先,應該去官網spring.io閱讀寫spring框架的理念,就好比讀一本書,要閱讀這本書的綱要,要明白為什麼要設計spring架構。
然後,應該分模塊閱讀,先從核心模塊開始閱讀:如:
IoC Container, Events, Resources, i18n, Validation, Data Binding, Type Conversion, SpEL, AOP.
那麼在閱讀的時候,英文能力差的話,可以使用翻譯軟體翻譯成中文閱讀,畢竟不是每個程序員英語都很棒,畢竟中國人看中國字更容易去理解。當然,有些翻譯過來的並不準確,這個時候可以利用網路,去查看那段不理解的地方。
然後,把spring的jar包下載下來,利用IDEA打開,可以使用download資源,會發現,每個方法上面都會有詳細的英文注釋。一邊看官方的說明,一邊查看代碼的編寫,不難發現,非常多的代碼寫得很精闢,所以十分考驗一個程序員的java基本功,特別是反射,JDK\CGLIB代理,和java常用的設計模式等。
『叄』 詳解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介面中的處理器方法。
『肆』 Spring源碼解析(一)- 容器的基本實現
Spring使用 基本的JavaBean 來完成以前只可能由EJB完成的事情,是個分層架構。Spring創建bean都需要通過 讀取 、 解析 、 校驗配置文件, 然後注冊創建成Bean。 Spring是一個Bean容器 , 主要作用是替我們管理bean對象 (簡單的Java類對象的生命周期)。不管框架如何強大,還是需要我們程序員來告訴其一些必要信息的(比如要 管理的bean對象的類相關信息、是否開啟組件掃檔納描 等),這些我們稱之為對 Spring框架的配置 ,目前主流的配置方式是 通過使用配置文件或註解。
Spring中最核心的兩個源雀類: DefaultListableBeanFactory、XmlBeanDifinitionReader。DefaultListableBeanFactory 是整個bean載入的核心部分,是Spring注冊及載入bean的默認實現 。XmlBeanDefinitionReader 主要使用reader屬性對資源文件進行讀取和注冊。
XML配置文件讀取是Spring中重要的功能,大部分Spring大部分功能都是 以配置作為切入點 。 XmlBeanFactory 繼承自 DefaultListableBeanFactory ,而對於 DefaultListableBeanFactory 不同的地方其實是在 XmlBeanFactory 中使用了自定義的XML讀取器 XmlBeanDefinitionReader ,主要用於從XML文檔中讀取 BeanDefinition, 實現了個性化的 BeanDefinitionReader 讀取, DefaultListableBeanFactory 繼承了 並實現了 以及 BeanDefinitionRegistry 介面。
Spring的配置文件讀取是通過ClasaPathResource進行封裝的 ,如:new ClassPathResource("bean.xml")。在java中, 將不同來源的資源的讀取邏輯抽象成URL ,通過注冊不同的 handler來處理。 一般handler的類型使用不同的前綴,URL沒有默認定義相對的path路徑,也 沒有提供相關方法對資源進行檢查 ,顧Spring對其內部需要使用到的資源做了屬於自己的抽象結構, 用Resource介面來封裝底層資源。
Resource 介面繼承 InputStreamSource(封裝了任何能返回InputStream的類)。
Resource介面抽象了所有Spring內部使用到的底層資源 ,首先它定義了3個能判斷當前資源狀態的方法: 存在性(exists)、可讀性(isReadable)、是否處於打開狀態(isOpen) 。有了Resource介面便可以對所有資源進行統一處理。 ClassPathResource 中的實現是通過class或 classLoader 提供的底層方法進行調用。以此完成對配置文件資源的封裝。
當通過Resource相關類完成了對配置文件進行封裝,接下來由 XmlBeanDefinitionReader 完成對配置文件的讀取工作。雹蠢早
XML文件的驗證模式有兩種:DTD、XSD(XML Schema).
DTD即文檔類型定義, 是一種XML約束模式語言,是XML文件的驗證機制 。是一種保證XML文檔格式正確的有效方法, 可以通過比較XML文檔和DTD文件來查看文檔是否符合規范,元素和標簽的使用是否正確 。一個DTD文檔包含:元素的定義規則、元素間關系的定義規則、元素可使用的屬性、可使用的實體或符號規則。 要使用DTD驗證模式需要在XML文件的頭部聲明。
XML Schema語言就是XSD。 XML Schema描述了XML文檔的結構。可以用一個指定的XML Schema來驗證某個XML文檔,以檢查該XML文檔是否符合其要求。也可以 通過XML Schema指定一個XML文檔所允許的結構和內容 。XML Schema本身也是一個XML文檔,符合XML語法結構,可以用通用的XML解析器解析它。
使用XML Schema文檔對XML實例進行校驗,要聲明名稱空間和指定該名稱空間所對應的XML Schema文檔存儲位置 。通過schemaLocation屬性來指定名稱空間所對應的XML Schema文檔的存儲地址(1、名稱空間URL;2、該名稱空間所標識的XML Schema文件地址或URL地址)。
另外驗證模式通過 XmlBeanDefinitionReader 中的setValidationMode方法進行設定。而 Spring 用來檢測驗證模式的方法實際上就是判斷是否包含 DOCTYPE ,如果包含就是 DTD ,否則就是 XSD 。
XML文件經過驗證模式,交由DocumentLoader進行解析成對應的 Document。 而解析的過程中存在這么一環節:(EntityResolver) 根據聲明去尋找對應的DTD定義,以便對文檔進行驗證認證 。也可以通過setEntityResolver設置DTD定義。EntityResolver它用來接收兩個參數publicId和systemId,xsd格式文件通常publicId為null。而對於不同的驗證模式採用不同的解析器進行解析,並把文件轉換成Document文件,用於提取及注冊bean。
Document 文件通過 BeanDefinitionDocumentReader 進行內部邏輯處理,並提取root用於作為參數繼續完成BeanDefinition的注冊。
『伍』 有沒有關於java深入一點的書推薦
學習的最好途徑就是看書「,這是我自己學習並且小有了一定的積累之後的第一體會。個人認為看書有兩點好處:
1.能出版出來的書一定是經過反復的思考、雕琢和審核的,因此從專業性的角度來說,一本好書的價值遠超其他資料。
2.對著書上的代碼自己敲的時候方便。
「看完書之後再次提升自我的最好途徑是看一些相關的好博文「,我個人認為這是學習的第二步,因為一本書往往有好幾百頁,好的博文是自己看書學習之後的一些總結和提煉,對於梳理學習的游蠢扮內容很有好處,當然這里不是說自己的學習方法,就不再扯下去了。
很多程序員們往往有看書的沖動,但不知道看哪些書,下面我就給各位Java程序猿們推薦一些好書(每本書的作者會加粗標紅),其中絕大多數都是我自己平時在看的書,也算是我對於平時讀的書做一個小總結和讀後感吧。
首先推薦的不是一本書,而是一個博客,也是我們博客園另外一位博友java_my_life。
目前市面上講解設計模式的書很多,雖然我前面講了看書是最好的,但是對設計模式感興趣的朋友們,我推薦的是這個博客。這位博友的設計模式講得非常非常好,我認為90%的內容都是沒有問題且很值得學習的,其講解設計模式的大體路線是:
隨便開篇點明該設計模式的定義
圖文並茂講解該設計模式中的結構
以詳細的代碼形式寫一下該種設計模式的實現
補充內容
講解該設計模式的優缺點
對於一個設計模式我們關注、學習的知識點,不就是上面這些嗎?
不過我要重點提醒一下網友們,同一種設計檔衫模式的寫法有多種,並不是說只有按某種寫法來寫才是這種設計模式。比方說適配器模式,我們關注適配器模式一定要關注的是什麼是適配器模式不是怎麼寫適配器模式,不要認為某段代碼不是按照適配器模式的寫法寫下來的它就不是適配器模式了,記住這一點,你在學習設計模式的時候一定會對代碼中用到的設計模式有更深入的理解。
1、深入理解Java虛擬機:JVM高級特性與最佳實踐
如果你不滿足於做一個只會寫ifelse的Java程序員,而是希望更進一步,我隨便舉幾個例子吧:
了解Java代碼的底層運行機制
定位性能問題
對整個系統進行性能調優
解決各種奇奇怪怪的線上線下問題
更加高級別的,為自己的項目量身定做一款適合自己項目的虛擬機
那麼Java虛擬機是你必學的一門技術。《深入理解Java虛擬機:JVM高級特性與最佳實踐》作者是周志明,這本書可以說是國內寫得最好的有關Java虛擬機的書籍,近半年,前前後後這本書我起碼看了有5遍。國內寫虛擬機的書除了這本,其實還有一些其他的,我也買過,不過粗略看下來,很多內容也是《深入理解Java虛擬機:JVM高神灶級特性與最佳實踐》此書裡面的。
另外值得一提的是,《深入理解Java虛擬機:JVM高級特性與最佳實踐》這本書,有電子版的,網上搜一下就能下載到了。不過建議有興趣的朋友還是去買書看,電子版本下載到的一般是比較老的版本,相比最新修訂版的《深入理解Java虛擬機:JVM高級特性與最佳實踐》,有很多作者新補充的知識點是沒有的。
2、HotSpot實戰
所有的Java虛擬機都是遵循著Java虛擬機規范來的,市面上的Java虛擬機幾十款,《深入理解Java虛擬機:JVM高級特性與最佳實踐》一書裡面講的虛擬機並不針對某種特定的虛擬機,而是從Java虛擬機規范的角度來講解Java虛擬機。
我們平時使用的乃至商用的大多數Java虛擬機都是Sun公司的HotSpot,大家cmd進入命令行,使用」java-version」命令就可以看到了。如果希望在Java虛擬機規范的基礎上更加深入地去理解虛擬機的一些細節是怎麼實現的,就可以看一下《HotSpot實戰》一書,作者是陳濤。不過由於HotSpot的源碼都是C/C++寫的,所以要求讀者有非常好的C/C++基礎,如果對這兩門語言不是很熟悉的朋友,看這本書可能對你幫助不是很大。
最後提一句,如果有興趣的朋友,不妨先去網上下載一個openJDK,HotSpot的源碼就在裡面。
3、Java並發編程實戰
這本書常常被列入Java程序員必讀十大書籍排行榜前幾位,不過個人不是很推薦這本書。
《Java並發編程實戰》作者是BrianGoetz,怎麼說呢,這本書前前後後我也看了兩遍左右,個人感受是:
文字多代碼少
講解多實踐少
我覺得這可能就是老外寫書的特點吧,因為Java是北美國家(加拿大、美國)開發和維護的,所以老外對Java方方面面的理論知識體系都掌握得是非常清楚和透徹的。翻開這本書看,多線程什麼用、什麼是死鎖、什麼是競爭、什麼是線程安全等等,方方面面的知識點都用大量的文字篇幅講解,不免讓人感覺十分枯燥,也難讓讀者有實質性的進步。我這本書看了兩遍也屬於一目十行意思,有興趣的地方就重點看一下。
無論如何,作為一本常常位於Jva程序員必讀十大書籍排行榜前幾名的書,還是一定要推薦給大家的。
4、java多線程編程核心技術
《Java多線程編程核心技術》作者高洪岩。想要學習多線程的朋友,這本書是我大力推薦的,我的個人博客裡面二十多篇的多線程博文都是基於此書,並且在這本書的基礎上進行提煉和總結而寫出來的。
此書和《Java並發編程實戰》相反,這本書的特點是大篇幅的代碼+小篇幅的精講解,可能這和中國人寫的書比較偏向實用主義的風格有關。本書關於線程安全、synchronized、Reentrant、Timer等等都用詳細的代碼進行了講解,而且每個大知識點下的多個小知識點都會詳細講解到,非常有實踐價值。
有興趣的朋友們,我相信只要你們跟著這本書裡面的代碼敲、運行、思考,三步走,對於多線程的使用與理解一定會進幾大步。
不過這本書的缺點就是對於Java並發包下的一些類像CountDownLatch、Semphore、CyclicBarrier、Future、Callable等都沒有講到,重點的CAS和AQS也沒有觸及,重點類的實現原理也沒有提。當然,這很深入了,在學習了這本書之後如果能再去對這些知識進行一些學習、研究的話,你一定會慢慢成長為一個很厲害的多線程高手。
5、EffectiveJava中文版
這是唯一一本我沒有買的書。初識這本書,是在我的博文Java代碼優化(長期更新)裡面,底下評論的時候有朋友提到了這本書,當時我說要去買,不過這兩個月一直都沒時間去逛書店,甚是遺憾,之後肯定會找時間去買這本書的。
《EffectiveJava中文版》的作者是JoshuaBloch,這個人就很厲害了,他是谷歌的首席架構師,屬於超級技術大牛級別了吧,呵呵。由於沒有看過這本書,所以我不好發表評論,但是從這本書的知名度以及其作者的來頭來看(多提一句,這本書也是Java之父JamesGosling博士推崇的一本書),我相信這一定是一本值得一看的好書。
好的代碼是每個Java程序員都應該去追求的,不是說我今天寫一段好代碼相比寫一段爛代碼對性能會有多大的提升,更多的應該是提升了代碼的可讀性以及可以規避許多潛在的、未知的問題,避免代碼上線之後出問題而花時間去維護—-無論從時間成本、人力成本還是風險成本來說,這都是非常高的。
6、深入分析JavaWeb技術內幕
《深入分析JavaWeb技術內幕》,作者許令波,淘寶工程師。
這本書我用一個字概括就是:全。真的非常全,HTTP、DNS、CDN、靜態化、Jetty、Tomcat、Servlet、Spring、MyBatis等等,什麼都有,涉及知識面非常廣,但又不像專門精講某個知識點的書籍一樣講得非常深入,感覺這本書就是盡量去用短的篇幅講清楚一些JavaWeb使用到的技術的內幕,讓讀者對這些知識點的技術內幕有一個理性的認識。
不過,盡管每個知識點的篇幅都不多,但是重點都基本講到了,是一本讓人真正有收獲的書。如果想進一步了解這些技術的技術內幕,就要自己去買相關書籍或者自己上網查資料了,有種拋磚引玉,或者說師傅領進門、修行在個人的感覺。
7、大型網站技術架構核心原理與案例分析
一個字評價這本書,_;兩個字評價這本書,很_;三個字評價這本書,非常_。呵呵,好了,再說下去可能別人以為我是水軍了。
《大型網站技術架構核心原理與案例分析》的作者是李智慧,原阿里巴巴技術專家。
Java的大多數應用都是用在Web上的,現在只要稍微大型一點的Web應用,都一定是一個分布式系統,那麼一個分布式系統用到了哪些技術?一個大型網站是如何從一個小型網站成長起來的?如何保證你的網站安全?分布式系統使用到了緩存,有哪些緩存?緩存的使用有哪些值得注意的事項?
關於分布式的知識點,都在這本書裡面有體現,只有你想不到,沒有他寫不到,而且寫得非常易懂,基本屬於看一兩遍,再記一些筆記就知道是怎麼一回事兒了。多看幾遍,對分布式的理解一定會加深不少。而且裡面不僅僅是分布式的知識,還非常接地氣地寫了如何做一個好的架構師,其實我認為這不僅僅是寫給想做架構師的讀者看的,就是給讀者一些建議,如何更好地提出意見、如何更讓別人關注你的聲音、如何看到他人的優點,入木三分,讓人獲益匪淺。
8、大型網站系統與Java中間件實踐
《大型網站系統與Java中間件實踐》作者曾憲傑,是淘寶的技術總監,算起來應該在阿里有至少P8的級別了吧。
這本書的部分內容和上面一本李智慧的《大型網站技術架構核心原理與案例分析》有所重合,像分布式系統的演化、CDN、CAP理論和BASE理論等等,這也更說明這些都是分布式系統或者說是一個大型網站重點關注的內容,當作一次再學習也不錯。
本書要突出的重點是中間件三個字,中間件是分布式系統中一個非常重要的東西,其最重要的作用應該就是解耦,降低模塊與模塊之間的強依賴,不同的模塊之間的依賴度降低,便可以各自獨立地開發自己的功能,這也可以說是軟體工程發展的目標和驅動力。
因此,本書有一部分的內容就是基於中間件,詳細講解了中間件與JMS的各種知識,適合對分布式系統比較熟悉並且想要往中間件方面有一定研究的讀者。
9、從Paxos到ZooKeeper分布式一致性原理與實踐
《從Paxos到ZooKeeper分布式一致性原理與實踐》,作者倪超,阿里巴巴工程師。
這本書是我最近在研讀的一本書,和上面的《大型網站系統與Java中間件實踐》一樣,屬於分布式組件的范疇,屬於有些深入的內容,當然也是我自己的個人興趣。當然,如果有志向做一個出色的大型網站架構師、公司的技術總監之類,這些知識當然是必須掌握的。
本書從分布式系統基本理論開始講起,講到Paxos演算法,最後慢慢引入到Zookeeper,循序漸進。當然,更多的我目前還不方便發表什麼看法,因為這本書的第二張Paxos演算法我都還沒有弄懂(Paxos演算法確實有些難以理解和不太易懂),接下來的章節還沒有看下去。
如果網友們所在的公司在使用Zookeeper,並且你又對Zookeeper感興趣想要研究一下它的原理的,這本書將是不二之選。
10、MySQL5.6從零開始學
《MySQL5.6從零開始學》,作者劉增傑和李坤。
作為一名Java程序員,我認為我們千萬不要覺得資料庫是DBA的事情,資料庫對一個Java程序員來說也是必須掌握的一門知識,豐富的資料庫性能優化經驗是一個頂尖程序員必備技能。
目前主流的資料庫有Oracle和MySQL,當然推薦大家的是MySQL,主要原因我認為有兩點:
1、MySQL相比Oracle更輕量級、更小、安裝和卸載更方便,SQL其實都是差不多的,如果想學資料庫,學MySQL就可以了,在家裡面可以自己方便地研究,如果你的公司使用Oracle,只要再用對比學習法,關注一下Oracle和MySQL的差別即可
2、隨著2009年阿里巴巴去IOE的運動的進行,目前國內的很多互聯網公司都會選擇MySQL作為它們使用的資料庫,因為MySQL免費,所以既省錢又不需要出了問題就依賴甲骨文公司
MySQL學習我推薦的是這本我自己學習看的《MySQL5.6從零開始學》,我是覺得挺好的這本書,書裡面的知識點很細致、很全面,讀者選擇書籍的標准大多不就是這兩點嗎?
11、Spring源碼深度解析
《Spring源碼深度解析》,作者郝佳。
Spring這個框架做得太好了,功能太強大了,以至於很多開發者都只知Spring,不知什麼是工廠、什麼是單例、什麼是代理(我面試別人的真實體會)。這種功能強大的框架內部一定是很復雜的實現,這就導致一旦你的程序使用Spring,出了問題,可能是Error、可能是Exception、可能是程序運行結果不是你的預期的,出現諸如此類問題的時候,將會讓你感到困惑,除了上網查資料或者問別人似乎沒有更好的解決辦法。
研讀Spring的源代碼不失為一種很好的學習方法,我個人認為這有很多好處:
理解框架內部的實現之後,可以主動去解決問題,而不需要依賴別人
Spring框架內部實現用到了很多設計模式,很好的代碼設計思路,這將會對你寫代碼、對你理解設計模式有很大的提高
研究Spring框架將會大大增強你讀代碼的能力,我相信只要你能研究清楚Spring內部是如何實現的,其他任何一個框架的源代碼都難不倒你
總而言之,我認為讀代碼的能力是一個普通的程序員和一個好的程序員之間最大的差別之一,前者只會把別人寫好的東西拿來用,後者不僅能用好,還清楚知道別人寫好的東西底層是如何實現的,在出現問題的時候可以輕松解決。
Spring源代碼,個人推薦《Spring源碼深度解析》一書,真要研究透並且寫清楚Spring源代碼,恐怕三四本書都不夠,作者在近400頁的篇幅中盡量去講解Spring源代碼是如何實現的,殊為不易,盡管無法講得完全,但是相信作者的講解配合上讀者自己的研究,一定可以對Spring的實現有更深度的理解。
以上就是我對Java高級部分應該看的書籍的推薦,希望可以對你有所幫助。說一點我的建議,我們學Java技術更重要的還是看視頻教程,我們只有看更多的視頻教程,不斷的練習,在腦海當中產生深刻的記憶。我永遠堅信我的一句話:書籍能詮釋的東西畢竟有限。
最後在這里推薦大家關注一下我的微信公眾號:Java新手學習,給你准備了一套最新的Java基礎精講視頻教程和Java系統學習路線,關注即可觀看。
『陸』 Spring事件監聽機制源碼解析
1.Spring事件監聽體系包括三個組件:事件、事件監聽器,事件廣播器。
事件:定義事件類型和事件源,需要繼承ApplicationEvent。
事件監聽器:用來監聽某一類的事件,並且執行具體業務邏輯,需要實現ApplicationListener 介面或者需要用@ListenerEvent(T)註解。好比觀察者模式中的觀察者。
事件多播器:負責廣播通知所有監聽器,所有的事件監聽器都注冊在了事件多播器中。好比觀察者模式中的被觀察者。Spring容器默認生成的是同步事件多播器。可以自定義事件多播器,定義為非同步方式。
創建 的過程中,會執行refresh()中的()方法。該方法先獲取bean工廠,然後判斷工廠是否包含了beanName 為 applicationEventMulticaster的bean。如果包含了,則獲取該bean,賦值給applicationEventMulticaster 屬性。如果沒有,則創建一個 對象,並且賦值給 applicationEventMulticaster 。實現了源碼如下:
監聽器的注冊有兩種,通過實現 ApplicationListener介面或者添加@EventListener註解。
注冊的邏輯實現在refresh()中的registerListeners()方法裡面。第一步,先獲取當前ApplicationContext中已經添加的 applicationListeners(SpringMVC源碼中有用到),遍歷添加到多播器中。第二步,獲取實現了ApplicationListener介面的listenerBeanNames集合,添加至多播器中。第三步,判斷是否有早期事件,如果有則發起廣播。
思考一下,上面的代碼中第二步為啥添加的是listenerBeanName?
如果監聽器是懶載入的話(即有@Lazy 註解)。那麼在這個時候創建監聽器顯然是不對的,這個時候不能創建監聽器。所以添加監聽器到多播器的具體邏輯放在初始化具體的監聽器之後。通過 BeanPostProcessor 的介面實現。具體的實現類是 ApplicationListenerDetector 。這個類是在 refreah()中prepareBeanFactory()方法中添加的。代碼如下:
在創建 的構造方法中,會執行org.springframework.context.annotation.AnnotationConfigUtils#(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 方法。這個方法中會添加兩個 beanDefs, 代碼如下:
EventListenerMethodProcessor:事件監聽器的BeanFactory後置處理器,在前期會創建 DefaultEventListenerFactory ,後期在創建好Bean之後,根據 EventListener 屬性,調用DefaultEventListenerFactory創建具體的 。
DefaultEventListenerFactory:監聽器的創建工廠,用來創建 。
EventListenerMethodProcessor 的類繼承圖如下:
在refreash的()中會調用 org.springframework.context.event.EventListenerMethodProcessor#postProcessBeanFactory方法,獲取EventListenerFactory 類型的 Bean。代碼如下:
在 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,創建完所有的單例Bean 之後,會遍歷所有Bean是否實現了 SmartInitializingSingleton 介面。如果實現介面會執行該 Bean 的 afterSingletonsInstantiated() 方法。代碼如下:
org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated 中會調用私有方法 processBean()進行 ApplicationEventAdatper 的創建。代碼如下:
可以通過調用 org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType) 方法進行事件的調用。代碼如下:
中的 multicasEvent,invokeListener,doInvokeListener 三個方法代碼如下:
SpringMVC中就是通過Spring的事件機制進行九大組件的初始化。
監聽器定義在FrameworkServlet類中,作為內部類。代碼如下:
監聽器的添加在org.springframework.web.servlet.FrameworkServlet# 中進行。通過SourceFilteringListener進行包裝。添加代碼如下:
在refresh中的registerListeners方法進行添加,代碼如下:
在refresh中的finishRefresh()方法中,會調用publishEvnet(new ContextRefreshedEvent(this))發布事件。進行多播器廣播,代碼如下
最終會調到FrameworkServlet.this.onApplicationEvent(event)。
『柒』 [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全家桶筆記:Spring+Spring Boot+Spring Cloud+Spring MVC
最近我整理了一下一線架構師的Spring全家桶筆記:Spring+Spring Boot+Spring Cloud+Spring MVC,分享給大家一起學習一下~ 文末免費獲取哦
Spring是一個輕量級控制反轉(IoC)和面向切面(AOP)的容器框架。Spring框架是由於軟體開發的復雜性而創建的。Spring使用的是基本的JavaBean來完成以前只可能由EJB完成的事情。然而,Spring的用途不僅僅限於伺服器端的開發。從簡單性、可測試性和松耦合性角度而言,絕大部分Java應用都可以從Spring中受益。
1.1 Spring面試必備題+解析
1.2 Spring學習筆記
(1)Spring源碼深入解析
(2)Spring實戰
1.3 Spring學習思維腦圖
Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。通過這種方式,Spring Boot致力於在蓬勃發展的快速應用開發領域(rapid application development)成為領導者。
2.1 Spring Boot面試必備題+解析
2.2 Spring Boot學習筆記
(1)Spring Boot實踐
(2)SpringBoot揭秘 快速構建微服務體系
2.3 SpringBoot學習思維腦圖
springcloud是微服務架構的集大成者,將一系列優秀的組件進行了整合。基於springboot構建,對我們熟悉spring的程序員來說,上手比較容易。通過一些簡單的註解,我們就可以快速的在應用中配置一下常用模塊並構建龐大的分布式系統。
3.1 Spring Cloud面試必備題+解析
3.2 Spring Cloud學習筆記
(1)Spring Cloud參考指南
SpringMVC是一種基於Java的實現MVC設計模式的請求驅動類型的輕量級Web框架,使用了MVC架構模式的思想,將web層進行職責解耦,基於請求驅動指的就是使用請求-響應模型,框架的目的就是幫助我們簡化開發
4.1 Spring MVC面試必備題+解析
4.2 Spring MVC學習筆記
(1)看透Spring MVC源代碼分析與實踐
(2)精通Spring MVC
最後分享一下一份JAVA核心知識點整理(PDF)