如今做Java尤其是web幾乎是避免不了和Spring打交道了,但是Spring是這樣的大而全,新鮮名詞不斷產(chǎn)生,學起來給人一種凌亂的感覺,我就在這里總結(jié)一下,理順頭緒。
Spring
Spring 概述
Spring 是一個開源框架,是為了解決企業(yè)應用程序開發(fā)復雜性而創(chuàng)建的(替代更加重量級的企業(yè)級Java技術(shù), 尤其是EJB),它完成了大量開發(fā)中的通用步驟,留給開發(fā)者的僅僅是與特定應用相關(guān)的部分,從而大大提高了企業(yè)應用的開發(fā)效率。
Spring 框架是一個分層架構(gòu),由 7 個定義良好的模塊組成。Spring 模塊構(gòu)建在核心容器之上,核心容器定義了創(chuàng)建、配置和管理 bean 的方式如下圖:
組成 Spring 框架的每個模塊都可以單獨存在,或者與其他一個或多個模塊聯(lián)合實現(xiàn)。每個模塊的功能如下:
Spring 核心容器:核心容器提供 Spring 框架的基本功能,管理著Spring應用中bean的創(chuàng)建、配置和管理。核心容器的主要組件是 BeanFactory,它是工廠模式的實現(xiàn)。BeanFactory 使用DI將應用程序的配置和依賴性規(guī)范與實際的應用程序代碼分開。
Spring 上下文:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。提供了一種框架式的對象訪問方法,有些象JNDI注冊器。Context封裝包的特性得自于Beans封裝包,并添加了對國際化(I18N)的支持(例如資源綁定),事件傳播,資源裝載的方式和Context的透明創(chuàng)建,比如說通過Servlet容器。Spring 上下文和Bean工廠都是 bean 容器 的實現(xiàn)。
Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向方面的編程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何對象支持 AOP。Spring AOP 模塊為基于 Spring 的應用程序中的對象提供了事務管理服務。
Spring DAO:JDBC DAO 抽象層提供了有意義的異常層次結(jié)構(gòu),可用該結(jié)構(gòu)來管理異常處理和不同數(shù)據(jù)庫供應商拋出的錯誤消息。異常層次結(jié)構(gòu)簡化了錯誤處理,并且極大地降低了需要編寫的異常代碼數(shù)量(例如打開和關(guān)閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結(jié)構(gòu)。
Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的對象關(guān)系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結(jié)構(gòu)。
Spring Web 模塊:Web 上下文模塊建立在應用程序上下文模塊之上,為基于 Web 的應用程序提供了上下文。
Spring MVC 框架:MVC 框架是一個全功能的構(gòu)建 Web 應用程序的 MVC 實現(xiàn)。通過策略接口,MVC 框架變成為高度可配置的,MVC 容納了大量視圖技術(shù),其中包括 JSP、Velocity、Tiles、iText 和 POI。
Spring 核心特點:IOC和AOP
控制反轉(zhuǎn)模式(IOC)也稱作依賴性介入(DI)的基本概念是:不創(chuàng)建對象,但是描述創(chuàng)建它們的方式。在代碼中不直接與對象和服務連接,但在配置文件中描述哪一個組件需要哪一項服務。容器 (在 Spring 框架中是 IOC 容器) 負責將這些聯(lián)系在一起。在典型的 IOC 場景中,容器創(chuàng)建了所有對象,并設置必要的屬性將它們連接在一起,決定什么時間調(diào)用方法。
Rod Johnson是第一個高度重視以配置文件來管理Java實例的協(xié)作關(guān)系的人,他給這種方式起了一個名字:控制反轉(zhuǎn)(Inverse of Control,IoC)。后來Martine Fowler為這種方式起了另一個名稱:依賴注入(Dependency Injection),因此不管是依賴注入,還是控制反轉(zhuǎn),其含義完全相同。
當某個Java對象(調(diào)用者)需要調(diào)用另一個Java對象(被依賴對象)的方法時,在傳統(tǒng)模式下通常有兩種做法
原始做法: 調(diào)用者主動創(chuàng)建被依賴對象,然后再調(diào)用被依賴對象的方法
簡單工廠模式: 調(diào)用者先找到被依賴對象的工廠,然后主動通過工廠去獲取被依賴對象,最后再調(diào)用被依賴對象的方法.
注意上面的主動二字,這必然會導致調(diào)用者與被依賴對象實現(xiàn)類的硬編碼耦合,非常不利于項目升級的維護。使用Spring框架之后,調(diào)用者無需主動獲取被依賴對象,調(diào)用者只要被動接受Spring容器為調(diào)用者的成員變量賦值即可,由此可見,使用Spring后,調(diào)用者獲取被依賴對象的方式由原來的主動獲取,變成了被動接受——所以Rod Johnson稱之為控制反轉(zhuǎn)。
另外從Spring容器的角度來看,Spring容器負責將被依賴對象賦值給調(diào)用者的成員變量——相當于為調(diào)用者注入它依賴的實例,因此Martine Fowler稱之為依賴注入。
AOP(Aspect Orient Programming)也就是面向切面編程,作為面向?qū)ο缶幊痰囊环N補充,已經(jīng)成為一種比較成熟的編程方式。其實AOP問世的時間并不太長,AOP和OOP互為補充,面向切面編程將程序運行過程分解成各個切面。
AOP專門用于處理系統(tǒng)中分布于各個模塊(不同方法)中的交叉關(guān)注點的問題,在JavaEE應用中,常常通過AOP來處理一些具有橫切性質(zhì)的系統(tǒng)級服務,如日志、事務管理、安全檢查、緩存、對象池管理等,AOP已經(jīng)成為一種非常常用的解決方案。
在典型的面向?qū)ο箝_發(fā)方式中,可能要將日志記錄語句放在所有方法和 Java 類中才能實現(xiàn)日志功能。在 AOP 方式中,可以反過來將日志服務模塊化,并以聲明的方式將它們應用到需要日志的組件上,這樣 Java 類就不需要知道日志服務的存在,也不需要考慮相關(guān)的代碼。所以,用 Spring AOP 編寫的應用程序代碼是松散耦合的。
Spring 優(yōu)點總結(jié)
低侵入式設計,代碼的污染極低:很多框架通過強迫應用繼承它們的類或?qū)崿F(xiàn)它們的接口而導致應用與框架綁死,而Spring是通過spring特有的注解和通用的pojo結(jié)合。Spring的非侵入編程模型意味著這個類在Spring應用和非Spring應用中都可以發(fā)揮同樣的作用。Spring的組件就是普通的Java Bean,這也使得單元測試可以不再依賴容器,編寫更加容易。
使用模板消除樣板式代碼:?如Spring的JdbcTemplate使得執(zhí)行數(shù)據(jù)庫操作時避免傳統(tǒng)的JDBC樣板代碼(創(chuàng)建一個數(shù)據(jù)庫連接,然后再創(chuàng)建一個語句對象,最后你才能進行查詢,關(guān)閉數(shù)據(jù)庫連接、語句和結(jié)果集)成為了可能。
獨立于各種應用服務器:基于Spring框架的應用,可以真正實現(xiàn)Write Once,Run Anywhere的承諾。
Spring的IoC容器降低了業(yè)務對象替換的復雜性,降低了了組件之間的耦合性:對象的依賴關(guān)系將由系統(tǒng)中負責協(xié)調(diào)各對象的第三方組件在創(chuàng)建對象的時候進行設定,所以對象無需自行創(chuàng)建或管理它們的依賴關(guān)系,依賴關(guān)系將被自動注入到需要它們的對象當中去。而且如果一個對象只通過接口而不是具體實現(xiàn)或初始化過程來表明依賴關(guān)系,那么這種依賴就能夠在對象本身毫不知情的情況下,用不同的具體實現(xiàn)進行替換。
Spring的AOP支持允許將一些通用任務如安全、事務、日志等進行集中式管理:?將核心業(yè)務和系統(tǒng)服務分離,保持POJO的簡單性和內(nèi)聚性,從而使他們各自達到更好的復用。
Spring的ORM和DAO提供了與第三方持久層框架的良好整合,并簡化了底層的數(shù)據(jù)庫訪問:
Spring的高度開放性,并不強制應用完全依賴于Spring,開發(fā)者可自由選用Spring框架的部分或全部:當Spring不能滿足需求時, 完全可以考慮其他選擇。事實上, Spring甚至提供了與其他第三方框架和類庫的集成點, 這樣你就不需要自己編寫這樣的代碼了。比如以前常用的SSH框架,現(xiàn)在常用的SSM框架
Spring包含許多項目,下面挑一些最常用的出來總結(jié)一下。
Spring MVC
Spring MVC是Spring中的基礎 Web 框架,基于模型-視圖-控制器(Model-View-Controller,MVC)模式實現(xiàn),它能夠幫你構(gòu)建像Spring框架那樣靈活和松耦合的Web應用程序。
在該框架下,一次web請求大致可以分為如下圖幾個步驟,這些劃分分離了職責,使得代碼靈活、維護性更好。
為了使用該框架,我們首先要配置DispatchServlet,也就是前端控制器,然后啟用Spring MVC,并編寫控制器,視圖,模型等等。
其中,DispatcherServlet是Spring MVC的核心,DispatcherServlet啟動的時候,它會創(chuàng)建Spring應用上下文,并加載配置文件或配置類中所聲明的bean或者自動掃描的bean,但是在Spring Web應用中,通常還會有另外一個應用上下文,這個應用上下文是由ContextLoaderListener創(chuàng)建的。DispatcherServlet加載包含Web組件的bean,如控制器、視圖解析器以及處理器映射,而ContextLoaderListener要加載應用中的其他bean,通常是驅(qū)動應用后端的中間層和數(shù)據(jù)層組件。
Spring MVC是一個強大靈活的Web框架。借助于注解,Spring MVC提供了近似于POJO的開發(fā)模式,這使得開發(fā)處理請求的控制器變得非常簡單,同時也易于測試。而且Spring MVC還支持多種視圖解析器如JSP,Tiles,Thymeleaf,使得前端界面的功能更強大,編寫更容易。
Spring Web Flow
Spring Web Flow是Spring MVC的一個擴展, 它為基于流程的會話式Web應用(購物車或者向?qū)Чδ埽┨峁┝酥С帧:喲灾且粋€流程框架,能夠引導用戶執(zhí)行一系列向?qū)Р襟E。
在Spring Web Flow中,流程是由三個主要元素定義的:狀態(tài)、轉(zhuǎn)移和流程數(shù)據(jù)。狀態(tài)( State)是流程中事件發(fā)生的地點,在流程中通過轉(zhuǎn)移的方式從一個狀態(tài)到另一個狀態(tài),流程的當前狀況稱為流程數(shù)據(jù)。
狀態(tài)分為:
行為( Action) 行為狀態(tài)是流程邏輯發(fā)生的地方
決策( Decision) 決策狀態(tài)將流程分成兩個方向, 它會基于流程數(shù)據(jù)的評估結(jié)果確定流程方向
結(jié)束( End) 結(jié)束狀態(tài)是流程的最后一站。 一旦進入End狀態(tài), 流程就會終止
子流程( Subflow) 子流程狀態(tài)會在當前正在運行的流程上下文中啟動一個新的流程
視圖( View) 視圖狀態(tài)會暫停流程并邀請用戶參與流程
轉(zhuǎn)移連接了流程中的狀態(tài)。流程中除結(jié)束狀態(tài)之外的每個狀態(tài),至少都需要一個轉(zhuǎn)移,這樣就能夠知道一旦這個狀態(tài)完成時流程要去向哪里。狀態(tài)可以有多個轉(zhuǎn)移,分別對應于當前狀態(tài)結(jié)束時可以執(zhí)行的不同的路徑。
當流程從一個狀態(tài)進行到另一個狀態(tài)時,它會帶走一些流程數(shù)據(jù)。有時候,這些數(shù)據(jù)只需要很短的時間(可能只要展現(xiàn)頁面給用戶)。有時候,這些數(shù)據(jù)會在整個流程中傳遞并在流程結(jié)束的時候使用。
Spring Web Flow 可以構(gòu)建會話式應用程序的Web框架,這是好的,但是感覺其配置只能用xml這個設計不太合理,尤其是當bean很多或者流程節(jié)點很多時都不好維護。
Spring Security
安全對于許多應用都是一個非常關(guān)鍵的切面,因為安全性是超越應用程序功能的一個關(guān)注點,應用系統(tǒng)的絕大部分內(nèi)容都不應該參與到與自己相關(guān)的安全性處理中。盡管我們可以直接在應用程序中編寫安全性功能相關(guān)的代碼,但更好的方式還是將安全性相關(guān)的關(guān)注點與應用程序本身的關(guān)注點進行分離,作為系統(tǒng)的一個切面。Spring Security就是通過AOP和Filter來為應用程序?qū)崿F(xiàn)安全性的。
使用Servlet規(guī)范中的Filter保護Web請求并限制URL級別的訪問。Spring Security還能夠使用Spring AOP保護方法調(diào)用——借助于對象代理和使用通知,能夠確保只有具備適當權(quán)限的用戶才能訪問安全保護的方法。
Spring Security非常靈活,能夠基于各種數(shù)據(jù)存儲來認證用戶。它內(nèi)置了多種常見的用戶存儲場景,如內(nèi)存、關(guān)系型數(shù)據(jù)庫以及LDAP。但我們也可以編寫并插入自定義的用戶存儲實現(xiàn)。
當為瀏覽器渲染HTML內(nèi)容時,你可能希望視圖中能夠反映安全限制和相關(guān)的信息。一個簡單的樣例就是渲染用戶的基本信息( 比如顯示“您已經(jīng)以……身份登錄”)。或者你想根據(jù)用戶被授予了什么權(quán)限,有條件地渲染特定的視圖元素。Spring Security本身提供了一個JSP標簽庫,而Thymeleaf通過特定的方言實現(xiàn)了與Spring Security的集成。借助于這些,可以很容易的實現(xiàn)對視圖的保護。
Spring Data
Spring Data 是為了簡化構(gòu)建基于 Spring 框架應用的數(shù)據(jù)訪問技術(shù),包括關(guān)系數(shù)據(jù)庫、NoSQL、Map-Reduce 框架、云數(shù)據(jù)服務等等,旨在提供一種通用、統(tǒng)一的編碼模式(但是并不是代碼完全一樣),使得在Spring中使用任何數(shù)據(jù)庫都變得非常容易。
Spring Data作為Spring Source的其中一個父項目,旨在統(tǒng)一和簡化對各類型持久化存儲,而不拘泥于是關(guān)系型數(shù)據(jù)庫還是NoSQL數(shù)據(jù)存儲。
目前的Spring Data 包含如下的模塊(或者說子項目):
Spring Data Commons
Spring Data JPA
Spring Data KeyValue
Spring Data LDAP
Spring Data MongoDB
Spring Data Gemfire
Spring Data REST
Spring Data Redis
Spring Data for Apache Cassandra
Spring Data for Apache Solr
Spring Data Couchbase (community module)
Spring Data Elasticsearch (community module)
Spring Data Neo4j (community module)
無論是哪種持久化存儲,數(shù)據(jù)訪問對象(DAO,即Data Access Objects)通常都會提供對單一域?qū)ο蟮腃RUD(創(chuàng)建、讀取、更新、刪除)操作、查詢方法、排序和分頁方法等。Spring Data則提供了基于這些層面的統(tǒng)一接口(CrudRepository,PagingAndSortingRepository)以及對持久化存儲的實現(xiàn)。
你可能接觸過某一種Spring模型對象——比如JdbcTemplate——來編寫訪問對象的實現(xiàn)。但是在基于Spring Data的數(shù)據(jù)訪問對象,我們只需定義和編寫一些查詢方法的接口(基于不同的持續(xù)化存儲, 定義有可能稍有不同),Spring Data會在運行時間生成正確的實現(xiàn)。
所有Spring Data的子項目都支持:
模板:處理資源分配和異常處理
對象、數(shù)據(jù)存儲映射:如ORM
對數(shù)據(jù)訪問對象的支持: 幫助我們編寫一些模板式語句如分頁排序
然而一些Spring Data子項目,如Spring Data Redis和Spring Data Riak都只是提供模板,這是由于其相應的數(shù)據(jù)存儲都只支持非結(jié)構(gòu)化的數(shù)據(jù),而不適用于對象的映射和查詢。
Spring Boot
Spring誕生時是Java企業(yè)版(Java Enterprise Edition, JEE,也稱J2EE)的輕量級代替品。無需開發(fā)重量級的Enterprise JavaBean(EJB),Spring為企業(yè)級Java開發(fā)提供了一種相對簡單的方法。
雖然Spring的組件代碼是輕量級的,但它的配置卻是重量級的。一開始,Spring用XML配置,而且是很多的XML配置,即使后來有基于注解的改善,我們依然難逃大量配置的魔爪。而Spring Boot讓這一切成為了過去,如果說Spring的目的是簡化程序的開發(fā),那么Spring Boot就是為了簡化Spring本身的開發(fā)。
Spring Boot依賴于自動配置技術(shù)將Spring應用中樣板式的配置移除掉,這樣就能讓我們免受于一大堆的配置之苦,更加專注于業(yè)務功能。Spring Boot同時還提供了多個Starter項目,拿來即可用,極大地簡化了編程任務。
它提供了四個主要的特性,能夠改變開發(fā)Spring應用程序的方式:
Spring Boot Starter: 它將常用的依賴分組進行了整合,將其合并到一個依賴中,這樣就可以一次性添加到項目的Maven或Gradle構(gòu)建中,這里可以找到目前所有的starter項目。
自動配置: Spring Boot的自動配置特性利用了Spring 4對條件化配置的支持,合理地推測應用所需的bean并自動化配置它們,減少了你自己需要配置的數(shù)量。
命令行接口(Command-line interface,CLI):Spring Boot的CLI發(fā)揮了Groovy編程語言的優(yōu)勢,并結(jié)合自動配置進一步簡化Spring應用的開發(fā)。
Actuator: 它為Spring Boot應用添加了一定的管理特性。
Spring Cloud
在進入主題之前,首先來看看微服務,簡單說來就是將原本單個獨立的大系統(tǒng)拆分為分布式的多個小型的服務,這些小型服務各自獨立運行,他們通過HTTP和RestFul API進行通信。
一個微服務一般完成某個特定的功能,比如下單管理、客戶管理等等。每一個微服務都是微型六角形應用,都有自己的業(yè)務邏輯和適配器。一些微服務還會發(fā)布API給其它微服務和應用客戶端使用。其它微服務完成一個Web UI,運行時,每一個實例可能是一個云VM或者是Docker容器。
微服務具有分布式系統(tǒng)的特性,如服務發(fā)現(xiàn),負載均衡,故障轉(zhuǎn)移,多版本,灰度升級,服務降級,分布式跟蹤。
Spring Cloud是一套完整的分布式系統(tǒng)解決方案,它的子項目涵蓋了所有實現(xiàn)分布式系統(tǒng)所需要的基礎軟件設施(包括配置管理、服務治理、智能路由、全局鎖等等)。基于Spring Boot,Spring Boot做較少的配置,便可成為Spring Cloud中的一個微服務,使用Spring Cloud的開發(fā)者可以快速的啟動服務或構(gòu)建應用、同時能夠快速和云平臺資源進行對接,使得開發(fā)部署極其簡單。
Spring Cloud專注于提供良好的開箱即用經(jīng)驗的典型用例和可擴展性機制覆蓋:
分布式/版本化配置:Spring Cloud Config
服務注冊和發(fā)現(xiàn):Netflix Eureka 或者 Spring Cloud Eureka(對前者的二次封裝)
路由:Spring Cloud Zuul 基于 Netflix Zuul
service - to - service調(diào)用:Spring Cloud Feign
負載均衡:Spring Cloud Ribbon 基于 Netflix Ribbon 實現(xiàn)
斷路器:Spring Cloud Hystrix
分布式消息傳遞:Spring Cloud Bus
后記
總結(jié)了一大堆,感覺Spring Boot是趨勢,畢竟效率是王道。然后就是Spring Data的各個項目,因為如今的數(shù)據(jù)源是越發(fā)的豐富。最后,近幾年微服務的概念挺火的,所以Spring Cloud也要多多了解。