隨筆:有人曾這樣評價spring,說它是Java語言的一個巔峯之做,稱呼它爲Java之美,今天,小編就領你們一塊兒來領略一下spring之美!html
Spring官方文檔:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/前端
聲明:此文章大部分轉載自唐彤,本人只是在原基礎上略做修改,對原文有興趣的能夠戳鏈接:java
在談spring以前,完美能夠先看一下從官網結果來的圖(固然是翻譯後的啦~),讓你們有一個大概的瞭解:ios
Spring框架是一個輕量級的解決方案,能夠一站式地構建企業級應用。Spring是模塊化的,因此能夠只使用其中須要的部分。能夠在任何web框架上使用控制反轉(IoC),也能夠只使用Hibernate集成代碼或JDBC抽象層。它支持聲明式事務管理、經過RMI或web服務實現遠程訪問,並可使用多種方式持久化數據。它提供了功能全面的MVC框架,能夠透明地集成AOP到軟件中。git
Spring被設計爲非侵入式的,這意味着你的域邏輯代碼一般不會依賴於框架自己。在集成層(好比數據訪問層),會存在一些依賴同時依賴於數據訪問技術和Spring,可是這些依賴能夠很容易地從代碼庫中分離出來。github
本文檔是Spring框架的參考指南,若是你有任何請求、評論或問題,請給咱們發郵件,關於框架自己的問題將在StackOverflow上討論(見https://spring.io.questions)。web
這篇參考指南提供了Spring框架的詳細信息,包括了對全部功能的全面理解,同時也包括一些重要概念的背景(好比,依賴注入)。算法
若是你纔開始使用Spring,能夠經過建立一個基於Spring Boot的應用開始使用Spring框架。Spring Boot提供了一種快速建立Spring應用的方式,它基於Spring框架,支持約定優於配置,使你能夠儘快啓動並運行。spring
可使用start.spring.io或遵循入門指南(好比,構建RESTful web應用入門)生成一個基本的項目。除了易於理解,這些指南匯集於一個個任務,它們大部分都是基於Spring Boot的,同時也包含了Spring包下的其它項目,以便你能夠考慮什麼時候使用它們解決特定的問題。sql
Spring框架是基於Java平臺的,它爲開發Java應用提供了全方位的基礎設施支持,而且它很好地處理了這些基礎設施,因此你只須要關注你的應用自己便可。
Spring可使用POJO(普通的Java對象,plain old java objects)建立應用,而且能夠將企業服務非侵入式地應用到POJO。這項功能適用於Java SE編程模型以及所有或部分的Java EE。
那麼,作爲開發者能夠從Spring得到哪些好處呢?
譯者注:①JMX,Java Management eXtension,Java管理擴展,是一個爲應用程序、設備、系統等植入管理功能的框架。JMX能夠跨越一系列異構操做系統平臺、系統體系結構和網絡傳輸協議,靈活的開發無縫集成的系統、網絡和服務管理應用。②JMS,Java Message Service,Java消息服務,是Java平臺上有關面向消息中間件(MOM)的技術規範,它便於消息系統中的Java應用程序進行消息交換,而且經過提供標準的產生、發送、接收消息的接口簡化企業應用的開發。
一個Java應用程序,從受限制的嵌入式應用到n層的服務端應用,典型地是由相互合做的對象組成的,所以,一個應用程序中的對象是相互依賴的。
Java平臺雖然提供了豐富的應用開發功能,可是它並無把這些基礎構建模塊組織成連續的總體,而是把這項任務留給了架構師和開發者。你可使用設計模式,好比工廠模式、抽象工廠模式、建立者模式、裝飾者模式以及服務定位器模式等,來構建各類各樣的類和對象實例,從而組成整個應用程序。這些設計模式是很簡單的,關鍵在於它們根據最佳實踐起了很好的名字,它們的名字能夠很好地描述它們是幹什麼的、用於什麼地方、解決什麼問題,等等。這些設計模式都是最佳實踐的結晶,因此你應該在你的應用程序中使用它們。
Spring的控制反轉解決了上述問題,它提供了一種正式的解決方案,你能夠把不相干組件組合在一塊兒,從而組成一個完整的可使用的應用。Spring根據設計模式編碼出了很是優秀的代碼,因此能夠直接集成到本身的應用中。所以,大量的組織機構都使用Spring來保證應用程序的健壯性和可維護性。
2004年Martin Fowler在他的網站上提出了關於控制反轉(IoC,Inversion of Control)的問題,「The question is, what aspect of control are [they] inverting?」,後來,他又建議從新命名這項原則,使其能夠自我解釋,從而提出了依賴注入(DI,Dependency Injection)的概念。
Spring大約包含了20個模塊,這些模塊組成了核心容器(Core Container)、數據訪問/集成(Data Access/Integration)、Web、AOP(面向切面編程,Aspect Oriented Programming)、Instrumentation、消息處理(Messaging)和測試(Test),以下圖:
圖 2.1. Spring框架概述
下面列出了每項功能對應的模塊及其主題,它們都有人性的名字(artifact name),這些名字與依賴管理工具中的artifact id 是相互對應的。
核心容器包括spring-core,spring-beans,spring-context,spring-context-support和spring-expression(SpEL,Spring表達式語言,Spring Expression Language)等模塊。
spring-core和spring-beans模塊是Spring框架的基礎,包括控制反轉和依賴注入等功能。BeanFactory是工廠模式的微妙實現,它移除了編碼式單例的須要,而且能夠把配置和依賴從實際編碼邏輯中解耦。
Context(spring-context)模塊是在Core和Bean模塊的基礎上創建起來的,它以一種相似於JNDI註冊的方式訪問對象。Context模塊繼承自Bean模塊,而且添加了國際化(好比,使用資源束)、事件傳播、資源加載和透明地建立上下文(好比,經過Servelet容器)等功能。Context模塊也支持Java EE的功能,好比EJB、JMX和遠程調用等。ApplicationContext接口是Context模塊的焦點。spring-context-support提供了對第三方庫集成到Spring上下文的支持,好比緩存(EhCache, Guava, JCache)、郵件(JavaMail)、調度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。
spring-expression模塊提供了強大的表達式語言用於在運行時查詢和操做對象圖。它是JSP2.1規範中定義的統一表達式語言的擴展,支持set和get屬性值、屬性賦值、方法調用、訪問數組集合及索引的內容、邏輯算術運算、命名變量、經過名字從Spring IoC容器檢索對象,還支持列表的投影、選擇以及聚合等。
spring-aop模塊提供了面向切面編程(AOP)的實現,能夠定義諸如方法攔截器和切入點等,從而使實現功能的代碼完全的解耦出來。使用源碼級的元數據,能夠用相似於.Net屬性的方式合併行爲信息到代碼中。
spring-aspects模塊提供了對AspectJ的集成。
spring-instrument模塊提供了對檢測類的支持和用於特定的應用服務器的類加載器的實現。spring-instrument-tomcat模塊包含了用於tomcat的Spring檢測代理。
Spring 4 包含的spring-messaging模塊是從Spring集成項目的關鍵抽象中提取出來的,這些項目包括Message、MessageChannel、MessageHandler和其它服務於消息處理的項目。這個模塊也包含一系列的註解用於映射消息到方法,這相似於Spring MVC基於編碼模型的註解。
數據訪問與集成層包含JDBC、ORM、OXM、JMS和事務模塊。
(譯者注:JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service)
spring-jdbc模塊提供了JDBC抽象層,它消除了冗長的JDBC編碼和對數據庫供應商特定錯誤代碼的解析。
spring-tx模塊支持編程式事務和聲明式事務,可用於實現了特定接口的類和全部的POJO對象。
(譯者注:編程式事務須要本身寫beginTransaction()、commit()、rollback()等事務管理方法,聲明式事務是經過註解或配置由spring自動處理,編程式事務粒度更細)
spring-orm模塊提供了對流行的對象關係映射API的集成,包括JPA、JDO和Hibernate等。經過此模塊可讓這些ORM框架和spring的其它功能整合,好比前面說起的事務管理。
spring-oxm模塊提供了對OXM實現的支持,好比JAXB、Castor、XML Beans、JiBX、XStream等。
spring-jms模塊包含生產(produce)和消費(consume)消息的功能。從Spring 4.1開始,集成了spring-messaging模塊。
Web層包括spring-web、spring-webmvc、spring-websocket、spring-webmvc-portlet等模塊。
spring-web模塊提供面向web的基本功能和麪向web的應用上下文,好比多部分(multipart)文件上傳功能、使用Servlet監聽器初始化IoC容器等。它還包括HTTP客戶端以及Spring遠程調用中與web相關的部分。
spring-webmvc模塊(即Web-Servlet模塊)爲web應用提供了模型視圖控制(MVC)和REST Web服務的實現。Spring的MVC框架可使領域模型代碼和web表單徹底地分離,且能夠與Spring框架的其它全部功能進行集成。
spring-webmvc-portlet模塊(即Web-Portlet模塊)提供了用於Portlet環境的MVC實現,並反映了spring-webmvc模塊的功能。
spring-test模塊經過JUnit和TestNG組件支持單元測試和集成測試。它提供了一致性地加載和緩存Spring上下文,也提供了用於單獨測試代碼的模擬對象(mock object)。
前面說起的構建模塊使得Spring在不少場景成爲一種合理的選擇,無論是資源受限的嵌入式應用仍是使用了事務管理和web集成框架的成熟的企業級應用。
圖2.2. 典型的成熟的Spring web應用程序
Spring的聲明式事務管理可使web應用完成事務化,就像使用EJB容器管理的事務。全部客制的業務邏輯均可以使用簡單的POJO實現,並用Spring的IoC容器進行管理。另外,還包括髮郵件和驗證功能,其中驗證功能是從web層分離的,由你決定何處執行驗證。Spring的ORM能夠集成JPA、Hibernate和JDO等,好比,使用Hibernate時,能夠繼續使用已存在的映射文件和標準的Hibernate的SessionFactory配置。表單控制器無縫地把web層和領域模型集成在一塊兒,移除了ActionForms和其它把HTTP參數轉換成領域模型的類。
圖2.3. 使用第三方web框架的Spring中間件
一些場景可能不容許你徹底切換到另外一個框架。然而,Spring框架不強制你使用它全部的東西,它不是非此即彼(all-or-nothing)的解決方案。前端使用Struts、Tapestry、JSF或別的UI框架能夠和Spring中間件集成,從而使用Spring的事務管理功能。僅僅只須要使用ApplicationContext鏈接業務邏輯,並使用WebApplicationContext集成web層便可。
圖2.4. 遠程調用使用場景
當須要經過web服務訪問現有代碼時,可使用Spring的Hessian-,Burlap-,Rmi-或者JaxRpcProxyFactory類,遠程訪問現有的應用並不是難事。
圖2.5. EJB-包裝現有的POJO
Spring框架也爲EJB提供了訪問抽象層,能夠從新使用現有的POJO並把它們包裝到無狀態的會話bean中,以使其用於可擴展的安全的web應用中。
依賴管理和依賴注入是兩碼事。爲了讓應用程序擁有這些Spring的很是棒的功能(如依賴注入),須要導入所需的所有jar包,並在運行時放在classpath下,有可能的話編譯期也應該放在classpath下。這些依賴並非被注入的虛擬組件,而是文件系統上典型的物理資源。依賴管理的處理過程涉及到定位這些資源、存儲並添加它們到classpath下。依賴多是直接的(好比運行時依賴於Spring),也多是間接的(好比依賴於commons-dbcp,commons-dbcp又依賴於commons-pool)。間接的依賴又被稱做「傳遞」,它們是最難識別和管理的。
若是準備使用Spring,則須要拷貝一份所需模塊的Spring的jar包。爲了便於使用,Spring被打包成一系列的模塊以儘量地減小依賴,好比,若是不是在寫一個web應用,那就不必引入spring-web模塊。這篇文檔中涉及到的Spring模塊,咱們使用spring-*或spring-*.jar的命名約定,其中,*表明模塊的短名字(好比,spring-core、spring-webmvc、spring-jms等等)。實際使用的jar包正常狀況下都是帶有版本號的(好比,spring-core-4.3.0.RELEASE.jar)。
每一個版本的Spring都會在如下地方發佈artifact:
所以,首先要作的事就是決定如何管理依賴關係,咱們通常推薦使用自動管理的系統,好比Maven、Gradle或Ivy,固然你也能夠手動下載全部的jar包。
下面列出了Spring的artifact,每一個模塊更完整的描述,參考 2.2 模塊 章節。
表2.1. Spring框架的artifact
groupId | artifactId | 描述 |
---|---|---|
org.springframework | spring-aop | 基於代理的AOP |
org.springframework | spring-aspects | 基於切面的AspectJ |
org.springframework | spring-beans | bean支持,包括Groovy |
org.springframework | spring-context | 運行時上下文,包括調度和遠程調用抽象 |
org.springframework | spring-context-support | 包含用於集成第三方庫到Spring上下文的類 |
org.springframework | spring-core | 核心庫,被許多其它模塊使用 |
org.springframework | spring-expression | Spring表達式語言 |
org.springframework | spring-instrument | JVM引導的檢測代理 |
org.springframework | spring-instrument-tomcat | tomcat的檢測代理 |
org.springframework | spring-jdbc | JDBC支持包,包括對數據源設置和JDBC訪問支持 |
org.springframework | spring-jms | JMS支持包,包括髮送和接收JMS消息的幫助類 |
org.springframework | spring-messaging | 消息處理的架構和協議 |
org.springframework | spring-orm | 對象關係映射,包括對JPA和Hibernate支持 |
org.springframework | spring-oxm | 對象XML映射 |
org.springframework | spring-test | 單元測試和集成測試組件 |
org.springframework | spring-tx | 事務基礎,包括對DAO的支持及JCA的集成 |
org.springframework | spring-web | web支持包,包括客戶端及web遠程調用 |
org.springframework | spring-webmvc | REST web服務及web應用的MVC實現 |
org.springframework | spring-webmvc-portlet | 用於Portlet環境的MVC實現 |
org.springframework | spring-websocket | WebSocket和SockJS實現,包括對STOMP的支持 |
Spring對大部分企業和其它外部工具提供了集成和支持,把強制性的外部依賴降到了最低,這樣就不須要爲了簡單地使用Spring而去尋找和下載大量的jar包了。基本的依賴注入只有一個強制性的外部依賴,那就是日誌管理(參考下面關於日誌管理選項的詳細描述)。
下面列出依賴於Spring的應用的基本配置步驟,首先使用Maven,而後Gradle,最後Ivy。在全部案例中,若是有什麼不清楚的地方,參考所用的依賴管理系統的文檔或查看一些範例代碼——Spring構建時自己使用Gradle管理依賴,因此咱們的範例大部分使用Gradle或Maven。
若是使用Maven做爲依賴管理工具,甚至不須要明確地提供日誌管理的依賴。例如,建立應用上下文並使用依賴注入配置應用程序,Maven的依賴關係看起來像下面同樣:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.0.RELEASE</version> <scope>runtime</scope> </dependency> </dependencies>
就這樣,注意若是不須要編譯Spring API,能夠把scope聲明爲runtime,這是依賴注入使用的典型案例。
上面的示例使用Maven中央倉庫,若是使用Spring的Maven倉庫(例如,里程碑或開發快照),須要在Maven配置中指定倉庫位置。
release版本:
<repositories> <repository> <id>io.spring.repo.maven.release</id> <url>http://repo.spring.io/release/</url> <snapshots><enabled>false</enabled></snapshots> </repository> </repositories>
里程碑版本:
<repositories> <repository> <id>io.spring.repo.maven.milestone</id> <url>http://repo.spring.io/milestone/</url> <snapshots><enabled>false</enabled></snapshots> </repository> </repositories>
快照版本:
<repositories> <repository> <id>io.spring.repo.maven.snapshot</id> <url>http://repo.spring.io/snapshot/</url> <snapshots><enabled>true</enabled></snapshots> </repository> </repositories>
使用Maven時可能會不當心混合了Spring不一樣版本的jar包。例如,你可能會發現第三方庫或其它的Spring項目存在舊版本的傳遞依賴。若是沒有明確地聲明直接依賴,各類各樣不可預料的狀況將會出現。
爲了解決這個問題,Maven提出了「物料清單式」(BOM)依賴的概念。能夠在dependencyManagement部分導入spring-framework-bom以保證全部的Spring依賴(無論直接仍是傳遞依賴)使用相同的版本。
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>4.3.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
使用BOM的另一個好處是再也不須要指定<version>屬性了:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <dependencies>
爲了在Gradle構建系統中使用Spring倉庫,須要在repositories部分包含合適的URL:
repositories {
mavenCentral()
// and optionally... maven { url "http://repo.spring.io/release" } }
能夠酌情把repositories URL中的/release修改成/milestone或/snapshot。一旦倉庫配置好了,就能夠按Gradle的方式聲明依賴關係了。
dependencies {
compile("org.springframework:spring-context:4.3.0.RELEASE") testCompile("org.springframework:spring-test:4.3.0.RELEASE") }
使用Ivy管理依賴關係有類似的配置選項。
在ivysettings.xml中添加resolver配置使Ivy指向Spring倉庫:
<resolvers> <ibiblio name="io.spring.repo.maven.release" m2compatible="true" root="http://repo.spring.io/release/"/> </resolvers>
能夠酌情把root URL中的/release修改成/milestone或/snapshot。一旦配置好了,就能夠按照慣例添加依賴了(在ivy.xml中):
<dependency org="org.springframework" name="spring-core" rev="4.3.0.RELEASE" conf="compile->runtime"/>
雖然使用支持依賴管理的構建系統是獲取Spring框架的推薦方法,可是也支持經過下載Spring的發行版zip文件獲取。
發行版zip文件發佈在了Sprng的Maven倉庫上(這只是爲了方便,不須要額外的Maven或其它構建系統去下載它們)。
瀏覽器中打開http://repo.spring.io/release/org/springframework/spring,並選擇合適版本的子目錄,就能夠下載發行版的zip文件了。發行文件以-dist.zip結尾,例如,spring-framework-{spring-version}-RELEASE-dist.zip。發行文件也包含里程碑版本和快照版本。
對於Spring來講日誌管理是很是重要的依賴關係,由於a)它是惟一的強制性外部依賴,b)每一個人都喜歡從他們使用的工具看到一些輸出,c)Spring集成了許多其它工具,它們都選擇了日誌管理的依賴。應用程序開發者的目標之一一般是在整個應用程序(包括全部的外部組件)的中心位置統一配置日誌管理,這是很是困難的由於如今有不少日誌管理的框架可供選擇。
Spring中強制的日誌管理依賴是Jakarta Commons Logging API(JCL)。咱們編譯了JCL,並使JCL的Log對象對繼承了Spring框架的類可見。對用戶來講全部版本的Spring使用相同的日誌管理庫很重要:遷移很簡單由於Spring保存了向後兼容,即便對於擴展了Spring的應用也能向後兼容。咱們是怎麼作到的呢?咱們讓Spring的一個模塊明確地依賴於commons-logging(JCL的典型實現),而後讓全部其它模塊都在編譯期依賴於這個模塊。例如,使用Maven,你想知道哪裏依賴了commons-logging,實際上是Spring確切地說是其核心模塊spring-core依賴了。
commons-logging的優勢是不須要其它任何東西就可使應用程序運轉起來。它擁有一個運行時發現算法用於在classpath中尋找其它日誌管理框架而且適當地選擇一個使用(或者告訴它使用哪一個)。若是不須要其它的功能了,你就能夠從JDK(java.util.logging或JUL)獲得一份看起來很漂亮的日誌了。你會發現大多數狀況下你的Spring應用程序工做得很好且日誌很好地輸出到了控制檯,這很重要。
不幸的是,commons-logging的運行時發現算法雖然對於終端用戶很方便,但存在必定的問題。若是咱們能讓時光倒流,從新開始Spring項目,咱們會使用不一樣的日誌管理依賴。首要選擇多是Simple Logging Facade for Java(SLF4J),它也被用於了其它一些使用Spring的工具中。
有兩種方式關掉commons-logging:
以下,在dependencyManagement中添加部分代碼就能夠排除掉commons-logging了:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.0.RELEASE</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
如今這個應用多是殘缺的,由於在classpath上沒有JCL API的實現,因此須要提供一個新的去修復它。下個章節咱們將以SLF4J爲例子爲JCL提供一個替代實現。
SLF4J是一個更乾淨的依賴,且運行時比commons-logging更有效率,由於它使用編譯期而非運行時綁定其它日誌管理框架。這也意味着你不得不明確地指出運行時想作什麼,並定義和配置它。SLF4J能夠綁定許多公共的日誌管理框架,因此一般你能夠選擇一個已經使用的,綁定它並配置和管理。
SLF4J能夠綁定許多公共的日誌管理框架,包括JCL,同時也是其它日誌管理框架和它自己的橋樑。因此爲了在Spring中使用SLF4J,須要用SLF4J-JCL橋樑代替commons-logging依賴。一旦這樣作了而後日誌記錄從Spring內部調用轉變成調用SLF4J API,所以,若是應用中的其它庫使用了這個API,而後將有一個統一的地方用於配置和管理日誌。
一般的選擇是把Spring橋接到SLF4J,而後從SLF4J到Log4J提供明確的綁定。須要提供4個依賴關係(且排除掉commons-logging):橋樑、SLF4J API、綁定到Log4J和Log4J的實現自己。在Maven中看起來像下面同樣:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.0.RELEASE</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.5.8</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.5.8</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.5.8</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> </dependencies>
彷佛這麼多依賴僅僅用於獲取日誌。在類加載器問題上,它應該表現得比commons-logging更好,尤爲是在像OSGi這樣嚴格的容器中。並且,它也有性能優點由於綁定發生在編譯期而非運行時。
對於SLF4J用戶更廣泛的選擇是直接綁定Logback,這須要更少的步驟,生成更少的依賴。這樣移除了額外的綁定由於Logback直接實現了SLF4J,因此僅僅須要兩個庫便可而不用四個庫(jcl-over-slf4j和logback)。這樣作的話還須要把slf4j-api依賴從其它外部依賴(不是Spring)中排除掉,由於在classpath下僅僅須要一個版本的API。
許多人使用Log4J做爲日誌管理框架。它是高效和完善的,實際上在構建和測試Spring的時候咱們運行時就是使用它。Spring也提供了一些工具用於配置和初始化Log4J,因此某些模塊在編譯期能夠選擇依賴於Log4J。
爲了使Log4J代替默認的JCL依賴(commons-logging),僅僅提供一個配置文件(log4j.properties或log4j.xml)放在classpath根目錄下便可。Maven中的配置以下:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.0.RELEASE</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> </dependencies>
下面是log4j.properties的樣例,用於打印日誌到控制檯:
log4j.rootCategory=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n log4j.category.org.springframework.beans.factory=DEBUG
許多人在一個容器中運行Spring應用程序,而這個容器自己又提供了JCL的實現。IBM的Websphere Application Server(WAS)是一個原型。這常常引發一些問題,並且不幸的是沒有很好的解決方案,簡單地從應用中排除掉commons-logging在大部分狀況下還不夠。
更清楚地描述:這個問題一般並不與JCL自己有關,甚至是commons-logging,而是他們綁定了commons-logging到另外一個框架(一般是Log4J)。這會失敗是由於commons-logging改變了在舊版本(1.0)和新版本(1.1)中執行運行時發現算法的方式,其中,舊版本在一些容器中還在使用,新版本是如今大部分人使用的。Spring沒有使用JCL API的其它部分,因此不會有什麼問題,可是一旦Spring或你的應用試圖記錄日誌就會發現Log4J不能工做了。(譯者注:此處的意思是即便發生了上面的衝突,Spring也不會去檢查,直接運行的時候須要打印日誌的時候纔會出錯)
在WAS這個案例中,最簡單的方法就是倒置類加載器的繼承(IBM稱做「parent last」,即把父類放後面),以便應用程序而不是容器控制JCL依賴。這種選擇並不老是管用的,在公共領域有不少其它建議的替代方案,且你的里程可能會隨着確切的版本和容器的特性而改變。(譯者注:此處的意思是上面介紹的方法並非惟一的,須要根據不一樣的版本和容器做出相應的方案)
Spring最初發行於2004年,從那之後有過幾回重大的修改,Spring 2.0提供了XML命名空間和AspectJ,Spring 2.5包含了註解驅動的配置,Spring 3.0以Java 5+爲框架的代碼基礎,並使用其新特性,諸如以@Configuration註解的模型等。
4.0版本是最近一次重大的修改,且首次全面支持Java 8的新特性。你仍然能夠繼續使用Java的舊版本,可是最低要求提高到了Java SE 6。咱們也利用此次重大修改移除了不少過期的類和方法。
升級到Spring 4.0的指導手冊參見Spring Framework GigHub Wiki。
新的spring.io網址提供了完整的入門指南幫你學習Spring。更多的指南請參考本文檔的 1. Spring入門。新網址也提供了對發佈在Spring下的許多項目的深刻理解。
若是你是Maven用戶,你可能會對如今發佈在每一個Spring版本中的物料清單POM文件感興趣。
4.0版本移除了全部過期的包以及許多過期的類和方法。若是從以前的版本升級過來,則須要保證修復全部對過期API的調用。
完整的改變請參考API Differences Report。
注意,可選的第三方依賴已經升級到2010/2011的版本(也就是說,Spring 4只支持發佈在2010年以後的版本),尤爲是,Hibernate 3.6+,EhCache 2.1+,Quartz 1.8+,Groovy 1.8+,Joda-Time 2.0+。有一個例外,Spring 4須要Hibernate Validator 4.3+和Jackson2.0+(Spring 3.2保留了對Jackson1.8/1.9的支持,但如今過期了)。
Spring 4.0對Java 8的幾個新特性提供了支持,容許使用lambda表達式,在Spring回調接口中使用方法引用。對java.time(JSR-310)有很好地支持,把幾個已存在的註解改造爲@Repeatable,還可使用java 8的參數名稱發現做爲替代方案來編譯啓用了調試信息的代碼(基於-parameters的編譯器標誌,譯者注:參數名稱發現是經過反射獲取參數的名稱,而不是類型)。
Spring保留了對舊版本Java和JDK的兼容,具體地說是Java SE 6和更高版本都全面支持(最低JDK6.18,發佈於2010年1月)。儘管如此,咱們依然建議基於Spring 4的新項目使用Java 7或者8。
Java EE 6+及其相關的JPA 2.0和Servlet 3.0,被認爲是Spring 4的基線。爲了兼容Google App Engine和舊的應用服務器,可能要在Servlet 2.5環境中部署Spring 4。然而,Servlet 3.0+是咱們強烈推薦的,而且它也是Spring測試的先決條件,也是模擬軟件包測試開發環境設置的先決條件。
若是你是WebSphere 7用戶,請必定要安裝JPA 2.0包,若是是WebLogic 10.3.4或更高版本,還要安裝JPA 2.0補丁,這樣Spring 4才能兼容這兩個服務器。
更有遠見的主意,Spring 4.0如今支持Java EE 7適用的規範,尤爲是JMS 2.0、JTA 1.二、JPA 2.一、Bean Validation 1.1和JSR-236 Concurrency Utilities。像往常同樣,這種支持只針對我的的使用,好比在Tomcat或獨立的環境中。儘管如此,當Spring應用部署在Java EE 7的服務器上依然運行良好。
注意,Hibernate 4.3是JPA 2.1的提供者,所以只在Spring 4.0中支持。一樣地,Hibernate Validator 5.0是Bean Validation 1.1的提供者。所以,這兩項並不被Spring 3.2官方支持。
從Spring 4.0開始,可使用Groovy DSL定義外部bean了。在概念上,這與使用XML配置bean相似,可是可使用更簡潔的語法。使用Groovy還能夠很容易地把bean定義直接嵌入到引導代碼中。例如:
def reader = new GroovyBeanDefinitionReader(myApplicationContext) reader.beans { dataSource(BasicDataSource) { driverClassName = "org.hsqldb.jdbcDriver" url = "jdbc:hsqldb:mem:grailsDB" username = "sa" password = "" settings = [mynew:"setting"] } sessionFactory(SessionFactory) { dataSource = dataSource } myService(MyService) { nestedBean = { AnotherBean bean -> dataSource = dataSource } } }
更多信息請查閱GroovyBeanDefinitionReader的javadocs。
核心容器有如下幾點改進:
保留了Servlet 2.5服務器的部署,但Spring 4.0如今主要關注Servlet 3.0+環境的部署。若是使用Spring MVC測試框架,須要保證在test classpath上包含Servlet 3.0的兼容JAR包。
除了下面要講的WebSocket方面的支持,在Spring的Web模塊還包含如下幾點改進:
新的spring-websocket模塊全面支持在web應用中客戶端與服務端基於WebSocket雙向通訊。它兼容JSR-356、Java WebSocket API,另外還提供了基於SockJS的後退選項(例如,WebSocket仿真)用於不支持WebSocket協議的瀏覽器(例如,IE < 10)。
新的spring-messaging模塊支持STOMP做爲WebSocket的子協議與一個註解程序模型一塊兒用於路由並處理來自WebSocket客戶端的STOMP消息。所以,一個@Controller能夠同時包含@RequestMapping和@MessageMapping方法用於處理HTTP請求和來自WebSocket客戶端的消息。新的spring-messaging模塊還包含從之前Spring集成項目提取出來的關鍵抽象做爲基於消息處理的應用的基礎,如Message、MessageChannel、MesaageHandler等。
更詳細的內容請參考 25 WebSocket支持 章節。
除了移除了spring-test模塊過期的代碼,Spring 4.0還引入了幾個新特性用於單元測試和集成測試:
Spring 4.1引入了一個更簡單的方法來註冊JMS監聽器,那就是使用@JmsListener註解bean的方法。XML的命名空間也獲得了加強以支持這項新特性(jms:annotation-driven),也能夠經過Java配置來徹底使用這項新特性(@EnableJms,JmsListenerContainerFactory),還可使用JmsListenerConfigurer來編程式地註冊監聽器。
Spring 4.1還能夠與4.0中引入的spring-messaging合做使用:
最後,Spring 4.1還提供瞭如下各類各樣的改進:
Spring 4.1支持JCache(JSR-107)註解,直接使用Spring已存在的緩存配置和基礎架構便可,不須要其它的改變。
Spring 4.1也極大地改進了它的緩存策略:
Spring 4.1還爲了添加putIfAbsent方法對CacheInterface作了重大改變。
Spring 4.2提供了一流的支持用於聲明和查找註解屬性的別名。新的@AliasFor註解能夠用來在單個註解內聲明一對別名屬性,或者聲明一個從自定義註解屬性到元註解屬性的別名。
例如,來自spring-test模塊的@ContextConfiguration如今定義以下:
public @interface ContextConfiguration {
@AliasFor("locations") String[] value() default {}; @AliasFor("value") String[] locations() default {}; // ... }
相似地,重寫了元註解屬性的註解如今也可使用@AliasFor細粒度地控制那些在註解層次結構中被重寫的屬性。實際上,如今能夠爲元註解的value屬性聲明一個別名。
例如,如今能夠像下面同樣開發一種重寫了自定義屬性的組合註解。
@ContextConfiguration
public @interface MyTestConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "value") String[] xmlFiles(); // ... }
參考Spring註解編程模型。
spring 4.3 容許併發調用給定的key,從而使得值只被計算一次。這是一項可選功能,經過@Cacheable的新屬性sync啓用。這項功能也使Cache接口作了重大改變,增長了get(Object key, Callable<T> valueLoader)方法。
spring 4.3 也改進了如下緩存方面的內容:
另外,spring 4.3的spring-core.jar中集成了更新的ASM 5.1和Objenesis 2.4。