文章作者:Tyan
博客:noahsnail.com
2.Spring框架介紹
Spring框架是一個(gè)為支持開發(fā)Java應(yīng)用提供全面基礎(chǔ)架構(gòu)的Java平臺(tái)钾麸。Spring處理基礎(chǔ)架構(gòu),因此你可以集中精力在你有應(yīng)用上讶迁。
Spring使你能創(chuàng)建簡(jiǎn)單Java對(duì)象(POJO)并能非侵入式的將企業(yè)服務(wù)應(yīng)用到簡(jiǎn)單Java對(duì)象(POJO)上。
作為一個(gè)應(yīng)用開發(fā)者,下面是一些你能從Spring平臺(tái)受益的例子:
- 在一個(gè)數(shù)據(jù)庫業(yè)務(wù)中執(zhí)行一個(gè)Java方法而不必處理業(yè)務(wù)APIs
- 使一個(gè)本地的Java方法可以遠(yuǎn)程調(diào)用而不必處理遠(yuǎn)程APIs
- 使一個(gè)本地Java方法變?yōu)楣芾聿僮鞫槐靥幚鞪MX APIs
- 使一個(gè)本地Java方法變?yōu)橄⑻幚砥鞫槐靥幚鞪MS APIs
2.1依賴注入和控制反轉(zhuǎn)
Java應(yīng)用——一個(gè)不精確的術(shù)語囚痴,既可以表示受限制的嵌入式應(yīng)用又可以表示N層服務(wù)端的企業(yè)級(jí)應(yīng)用——通常由許多對(duì)象構(gòu)成昵济,這些對(duì)象協(xié)作形成完整的應(yīng)用程序铲觉。因此一個(gè)應(yīng)用程序中的對(duì)象是相互***依賴***的逼蒙。
盡管Java平臺(tái)提供了大量的應(yīng)用開發(fā)功能贡茅,但是它缺少把這些基本構(gòu)建模塊組織成一個(gè)連貫整體的方法,并把組織基本構(gòu)建模塊的任務(wù)留給了架構(gòu)師和開發(fā)者其做。雖然你可以使用設(shè)計(jì)模式例如***工廠模式、抽象工廠模式赁还、生成器模式妖泄、裝飾模式、服務(wù)定位模式***來創(chuàng)建構(gòu)成應(yīng)用的各種類和對(duì)象實(shí)例艘策,但這些設(shè)計(jì)模式很簡(jiǎn)單:命名的最佳方法蹈胡、模式的作用描述、應(yīng)用模式的位置朋蔫、模式解決的問題等等罚渐。模式使最佳實(shí)踐形式化了,這意味著你必須在你的應(yīng)用中***自己實(shí)現(xiàn)它***驯妄。
Spring框架中的***控制反轉(zhuǎn)***(IoC)組件通過提供一種形式化方法解決了這個(gè)問題荷并,這個(gè)形式化方法將不同的組件創(chuàng)建到一個(gè)隨時(shí)可用的完整的工作應(yīng)用中。Spring框架將形式化的設(shè)計(jì)模式編碼成了你可以集成到你自己的應(yīng)用中的最好對(duì)象青扔。許多組織和機(jī)構(gòu)用這種方式應(yīng)用Spring框架來構(gòu)建魯棒的源织、***可維護(hù)***的應(yīng)用。
背景
"問題是什么是控制反轉(zhuǎn)微猖?" 2004年Martin Fowler在他的網(wǎng)站上提出了這個(gè)關(guān)于控制反轉(zhuǎn)(IoC)問題谈息。Fowler建議重新命名這個(gè)原理使它更一目了然并且提出了依賴注入。
2.2 模塊
Spring框架包含的功能大約由20個(gè)模塊組成凛剥。這些模塊按組可分為核心容器侠仇、數(shù)據(jù)訪問/集成,Web犁珠,AOP(面向切面編程)逻炊、設(shè)備互亮、消息和測(cè)試,如下圖所示嗅骄。
圖2.1 Spring框架概述
接下來的章節(jié)列出了每個(gè)功能可用的模塊胳挎、它們的工件名字以及它們包含的主題。工件名字與依賴管理工具中使用的***artifact IDs***有關(guān)溺森。
2.2.1 核心容器
核心容器功能包括`spring-core`, `spring-beans`, `spring-context`, `spring-context-support`, and `spring-expression`(Spring表現(xiàn)語言)模塊慕爬。
`spring-core`和`spring-beans`模塊提供了框架的基礎(chǔ)結(jié)構(gòu)部分,包含控制反轉(zhuǎn)(IoC)和依賴注入(DI)功能屏积。`BeanFactory`是工廠模式的高級(jí)實(shí)現(xiàn)医窿。它去掉了程序單例模式的需求并且允許你從實(shí)際的程序邏輯中解耦配置和依賴的指定。
上下文(`spring-context`)模塊建立在由Core模塊和Beans模塊提供的堅(jiān)實(shí)基礎(chǔ)上:它是在類似于JNDI注冊(cè)表式的框架風(fēng)格模式中訪問對(duì)象的一種方法炊林。上下文模塊繼承了Beans模塊的功能姥卢,并添加了對(duì)國際化(例如使用資源捆綁)、事件傳播渣聚、資源加載和上下文透明創(chuàng)建(例如通過Servlet容器)的支持独榴。上下文模塊也支持Java EE功能例如EJB,JMX和基本的遠(yuǎn)程奕枝。`ApplicationContext`接口是上下文模塊的焦點(diǎn)棺榔。`spring-context-support`支持將第三方庫集成進(jìn)Spring應(yīng)用程序上下文中,特別是緩存(EhCache, JCache)和定時(shí)執(zhí)行(CommonJ, Quartz)隘道。
2.2.2 面向切面編程(AOP)和設(shè)備(Instrumentation)
`spring-aop`模塊提供了***AOP*** Alliance-compliant(AOP聯(lián)盟)面向切面編程的實(shí)現(xiàn)症歇,例如允許你自定義方法攔截器和切入點(diǎn)來清晰的解耦功能實(shí)現(xiàn)上應(yīng)該分開的代碼。使用源碼級(jí)的元數(shù)據(jù)功能谭梗,你也可以將行為信息合并到你的代碼中忘晤,在某種程度上這類似于.NET的屬性值。
獨(dú)立的`spring-aspects`模塊提供了與AspectJ的集成激捏。
`spring-instrument`模塊提供了類設(shè)備支持和類加載器的實(shí)現(xiàn)设塔,它們可以在某些應(yīng)用服務(wù)器中使用。`spring-instrument-tomcat`模塊包含了Tomcat的Spring設(shè)備代理远舅。
2.2.3 消息
Spring 4框架中包含了`spring-messaging`模塊壹置,它對(duì)***Spring集成***項(xiàng)目例如`Message`, `MessageChannel`, `MessageHandler`和其它作為消息應(yīng)用服務(wù)基礎(chǔ)的項(xiàng)目進(jìn)行了重要的抽象。這個(gè)模塊也包含了一系列將消息映射到方法上的注解表谊,這個(gè)注解與基于編程模型Spring MVC注解類似钞护。
2.2.4 數(shù)據(jù)訪問/集成
***數(shù)據(jù)訪問/集成***層包括JDBC,ORM,OXM,JMS和事務(wù)模塊。
`spring-jdbc`模塊提供了JDBC抽象層爆办,不需要再編寫單調(diào)的JDBC代碼难咕,解析數(shù)據(jù)庫提供商指定的錯(cuò)誤編碼。
`spring-tx`模塊為實(shí)現(xiàn)指定接口和所有的簡(jiǎn)單Java對(duì)象(POJOs)的類提供編程式(programmatic)和聲明式(declarative)的業(yè)務(wù)管理。
`spring-orm`模塊提供流行的對(duì)象關(guān)系映射APIs的集成層余佃,包括JPA和Hibernate暮刃。在使用`spring-orm`模塊時(shí),你可以將Spring的其它功能與這些O/R-mapping框架結(jié)合起來使用爆土,例如前面提到的簡(jiǎn)單聲明式業(yè)務(wù)管理的功能椭懊。
`spring-oxm`模塊提供對(duì)Object/XML映射實(shí)現(xiàn)例如JAXB,Castor步势,JiBx和XStream的抽象層氧猬。
`spring-jms`模塊(Java消息服務(wù))包含產(chǎn)生和處理小心的功能。從Spring 4.1框架開始它提供了與`spring-messaging`的集成坏瘩。
2.2.5 網(wǎng)絡(luò)
網(wǎng)絡(luò)層包含`spring-web`, `spring-webmvc`和`spring-websocket`模塊盅抚。
`spring-web`模塊提供基本的面向網(wǎng)絡(luò)集成功能,例如multipart文件上傳功能倔矾,使用Servlet監(jiān)聽器來初始化Ioc容器和面向網(wǎng)絡(luò)的應(yīng)用程序上下文妄均。它也包含了HTTP客戶端和Spring遠(yuǎn)程支持中網(wǎng)絡(luò)相關(guān)的部分。
`spring-webmvc`模塊(也被稱為***Web-Servlet***模塊)包含了Spring的model-view-controller(MVC)和REST Web Services的網(wǎng)絡(luò)應(yīng)用實(shí)現(xiàn)哪自。Spring的MVC框架提供了對(duì)域模型代碼丰包,web表單,Spring框架其他功能的完全分離壤巷。
2.2.6 測(cè)試
`spring-test`模塊支持單元測(cè)試烫沙,Spring組件和JUnit或TestNG的集成測(cè)試。它提供了Spring的`ApplicationContexts`加載和這些上下文緩存的一致隙笆。它也提供了可以單獨(dú)測(cè)試代碼的模擬對(duì)象。
2.3 使用場(chǎng)景
前面描述的構(gòu)建模塊使Spring在許多場(chǎng)景中都有一個(gè)合理選擇升筏,從運(yùn)行在資源受限的嵌入式應(yīng)用到全面成熟的企業(yè)級(jí)應(yīng)用都在使用Spring的業(yè)務(wù)管理功能和網(wǎng)絡(luò)框架集成撑柔。
圖2.2標(biāo)準(zhǔn)成熟的Spring web應(yīng)用
Spring的聲明式業(yè)務(wù)管理功能使web應(yīng)用全面的事務(wù)化,如果你用過EJB容器管理業(yè)務(wù)的話你會(huì)發(fā)現(xiàn)它們基本一樣您访。你所有自定義的業(yè)務(wù)邏輯都可以用POJOs實(shí)現(xiàn)并通過Spring的IoC容器管理铅忿。附加業(yè)務(wù)包括支持郵件發(fā)送和驗(yàn)證,這個(gè)是獨(dú)立于web層之外的灵汪,你可以自由選擇驗(yàn)證規(guī)則執(zhí)行的位置檀训。Spring對(duì)ORM的支持與JPA和Hibernate進(jìn)行了集成;例如享言,當(dāng)你使用Hibernate時(shí)峻凫,你可以繼續(xù)使用你現(xiàn)有的映射文件和標(biāo)準(zhǔn)的Hibernate `SessionFactory`配置。表單控制器被無縫的將web層和領(lǐng)域模型進(jìn)行了集成览露,對(duì)于你的領(lǐng)域模型來講不再需要`ActionForms`或其它的將HTTP參數(shù)轉(zhuǎn)換成值的類荧琼。
圖2.3. 使用第三方web框架的Spring中間層
有時(shí)候環(huán)境不允許你完全轉(zhuǎn)成一個(gè)不同的框架。Spring框架***不***強(qiáng)迫你都采用它內(nèi)部的東西;它不是一個(gè)***要么全有要么全無***的解決方案∶現(xiàn)有的采用Struts,Tapestry,JSF或其它UI框架構(gòu)建的前端可以與基于Spring的中間層進(jìn)行集成堰乔,這可以讓你使用Spring的業(yè)務(wù)功能。你只需要簡(jiǎn)單的用`ApplicationContext`和`WebApplicationContext`綁定你的業(yè)務(wù)邏輯然后集成到web層即可脐恩。
圖2.4. 遠(yuǎn)程應(yīng)用場(chǎng)景
當(dāng)你需要通過web服務(wù)訪問現(xiàn)有代碼時(shí)镐侯,你可以使用Spring的`Hessian-`, `Rmi-` 或 `HttpInvokerProxyFactoryBean`類。這能讓遠(yuǎn)程訪問現(xiàn)有應(yīng)用變得很容易驶冒。
Figure 2.5. EJBs-包裝現(xiàn)有的POJOs
Spring框架也為企業(yè)JavaBeans提供了訪問和抽象層苟翻,使你能重用你現(xiàn)有的POJOs,為了可擴(kuò)展使用可以將它們包裝成無狀態(tài)的session beans只怎,自動(dòng)防故障的web應(yīng)用可能需要聲明安全袜瞬。
2.3.1 依賴管理和命名約定
依賴管理和依賴注入是完全不同的兩件事。為了能你的應(yīng)用中使用Spring的優(yōu)秀特性(像依賴注入)身堡,你需要收集所有必要的庫(jar文件)并在運(yùn)行時(shí)將它們添加到classpath中邓尤,有可能在編譯時(shí)就需要添加。這些依賴不是要被注入的虛擬組建贴谎,而是文件系統(tǒng)中的物理資源(通常情況下)汞扎。這些依賴管理的過程包括資源的定位、存儲(chǔ)和添加到classpath中擅这。依賴可以是直接的(例如:我的應(yīng)用在運(yùn)行時(shí)依賴Spring)澈魄,或間接的(例如:我的應(yīng)用依賴`commons-dbcp`,而它依賴`commons-pool`)仲翎。間接依賴也被稱為"傳遞式"的痹扇,這些依賴也是最難識(shí)別和管理的。
如果你想使用Spring溯香,你需要有包含你需要的Spirng功能的jar庫副本鲫构。為了使這個(gè)更容易,Spring被打包成了一系列盡可能將依賴分離開的模塊玫坛,例如你不想寫web應(yīng)用那你就不需要spring-web模塊结笨。為了在本指南中談及Spring的庫模塊,我們使用了一個(gè)簡(jiǎn)寫命名約定`spring-*`或`spring-*.jar`湿镀,`*`表示模塊的簡(jiǎn)寫名字(例如`spring-core`, `spring-webmvc`, `spring-jms`等等)炕吸。實(shí)際中你使用的jar文件名字通常是模塊名加上版本號(hào)(例如`spring-core-5.0.0.BUILD-SNAPSHOT.jar`)。
Spring框架的每次發(fā)布都會(huì)下面的地方公布artifacts:
Maven Central勉痴,Maven查詢的默認(rèn)倉庫赫模,使用時(shí)不需要任何特定的配置。Spring依賴的許多共通庫也可以從Maven Central獲得蒸矛,Spring社區(qū)的很大一部分都在使用Maven進(jìn)行依賴管理嘴瓤,因此這對(duì)他們來說是很方便的扫外。jar包的命名形式是
spring-*-<version>.jar
,Maven GroupId是org.springframework
廓脆。-
由Spring掌管的公開Maven庫筛谚。除了最終的GA release(公開可獲得的版本)之外,這個(gè)倉庫也有開發(fā)版本的快照和milestone版本停忿。jar包的命名形式和Maven Central一樣驾讲,這是一個(gè)可以使用Spring開發(fā)版本有用地方,而其它的庫部署在Maven Central席赂。這個(gè)庫也包含的捆綁分布的zip文件吮铭,這個(gè)zip文件中所有的Spring jar包被捆綁到一起很容易下載。
你將在下面找到Spring artifacts列表颅停。想要每個(gè)模塊更全面的描述谓晌,請(qǐng)看2.2小節(jié)。
表 2.1. Spring Framework Artifacts
Spring依賴和依賴Spring
雖然Spring提供集成并支持大范圍內(nèi)的企業(yè)和其它外部工具癞揉,但它有意使它的強(qiáng)制性依賴到一個(gè)絕對(duì)最小化的程度:對(duì)于簡(jiǎn)單的用例你不應(yīng)該為了使用Spring而定位和下載(即使是自動(dòng)的)許多jar庫纸肉。對(duì)于基本的依賴注入僅有一個(gè)強(qiáng)制性的外部依賴,那個(gè)依賴是關(guān)于日志的(在下面可以看到日志選擇更詳細(xì)的描述)喊熟。
接下來我們概述配置一個(gè)依賴于Spring的應(yīng)用需要的基本步驟柏肪,首先Maven的,其次是Gradle的芥牌,最后是Ivy的烦味。在所有的案例中,如果有任何不清楚的地方壁拉,請(qǐng)參考你的依賴管理系統(tǒng)的文檔谬俄,或者看一些示例代碼——Spring本身構(gòu)建時(shí)使用Gradle來管理依賴,我們例子中大多數(shù)是使用Gradle和Maven的弃理。
Maven依賴管理
如果你正在使用Maven來進(jìn)行依賴管理溃论,那你不必顯式的提供日志依賴。例如案铺,為了創(chuàng)建一個(gè)應(yīng)用上下文宿亡,使用依賴注入來配置一個(gè)應(yīng)用铅碍,你的Maven依賴看上去是這樣的:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.0.BUILD-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
</dependencies>
就是它抄瓦。注意如果你不需要編譯Spring APIs壁却,scope可以被聲明成rumtime盛末,這是典型的基本依賴注入的情況挫剑。
上面的例子是采用Maven中心倉庫的鸠蚪。為了使用Spring Maven倉庫(例如:使用milestone版本或snapshot版本)肠阱,你需要在Maven配置中指定倉庫的位置测僵,完整的版本:
<repositories>
<repository>
<id>io.spring.repo.maven.release</id>
<url>http://repo.spring.io/release/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
對(duì)于milestone版本:
<repositories>
<repository>
<id>io.spring.repo.maven.milestone</id>
<url>http://repo.spring.io/milestone/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
對(duì)于snapshot版本:
<repositories>
<repository>
<id>io.spring.repo.maven.snapshot</id>
<url>http://repo.spring.io/snapshot/</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
Maven "材料清單" 依賴
在使用Maven時(shí)街佑,有可能會(huì)偶然的將不同版本的Spring JARs混合起來谢翎。例如,你可能找到一個(gè)第三方庫沐旨,或另一個(gè)Spring項(xiàng)目森逮,通過傳遞依賴進(jìn)入了一個(gè)更舊的版本。如果你忘了自己顯式的聲明一個(gè)直接依賴磁携,會(huì)產(chǎn)生各種意想不到的問題褒侧。
為了解決這種問題,Maven支持"材料清單"(BOM)依賴的概念谊迄。你可以在你的`dependencyManagement`部分導(dǎo)入`spring-framework-bom`來確保所有的Spring依賴(直接和傳遞的)都是同一個(gè)版本闷供。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>5.0.0.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
使用BOM的額外好處是當(dāng)依賴Spring框架的artifacts時(shí)你不再需要指定`<version>`屬性:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependencies>
Gradle依賴管理
為了在Gradle構(gòu)建系統(tǒng)中使用Spring倉庫,在`repositories`部分需要包含合適的URL:
repositories {
mavenCentral()
// and optionally...
maven { url "http://repo.spring.io/release" }
}
當(dāng)合適的時(shí)候你可以修改`repositories`的URL從`/release`到`/milestone`或`/snapshot`统诺。一旦一個(gè)倉庫被配置了歪脏,你可以用通常的Gradle方式聲明依賴:
dependencies {
compile("org.springframework:spring-context:5.0.0.BUILD-SNAPSHOT")
testCompile("org.springframework:spring-test:5.0.0.BUILD-SNAPSHOT")
}
Ivy依賴管理
如果你更喜歡使用Ivy來管理依賴,這有類似的配置選擇粮呢。
為了配置Ivy指定Spring倉庫婿失,添加下面的解析器到你的`ivysettings.xml`:
<resolvers>
<ibiblio name="io.spring.repo.maven.release"
m2compatible="true"
root="http://repo.spring.io/release/"/>
</resolvers>
當(dāng)合適的時(shí)候你可以更改根URL從`repositories`的URL從`/release`到`/milestone`或`/snapshot`。
一旦配置了鬼贱,你可以通過一般的方式添加依賴移怯。例如(在`ivy.xml`):
<dependency org="org.springframework"
name="spring-core" rev="5.0.0.BUILD-SNAPSHOT" conf="compile->runtime"/>
發(fā)行版Zip文件
盡管使用一個(gè)支持依賴管理的構(gòu)建系統(tǒng)是獲得Spring框架的推薦方式,但仍然可以下載發(fā)行版的Zip文件这难。
發(fā)行版的zips是被發(fā)布到Spring Maven倉庫(這只是為了我們的方便舟误,為了下載它們你不需要Maven或任何其它的構(gòu)建系統(tǒng))。
為了下載發(fā)行版zip姻乓,打開瀏覽器輸入[http://repo.spring.io/release/org/springframework/spring](http://repo.spring.io/release/org/springframework/spring)嵌溢,然后選擇你想要的版本的合適子文件夾。發(fā)行版文件以`-dist.zip`結(jié)尾蹋岩,例如spring-framework-{spring-version}-RELEASE-dist.zip赖草。發(fā)行版也可以公布milestone版本或snapshots版本。
2.3.2 日志
日志對(duì)于Spring來說是一個(gè)非常重要的依賴剪个,因?yàn)椋?a)*它是唯一的強(qiáng)制性外部依賴秧骑,*b)*每個(gè)人都喜歡從他們使用的工具中看到一些輸出,*c)*Spring集成了許多其它的工具扣囊,這些工具也選擇了日志依賴乎折。應(yīng)用開發(fā)者的一個(gè)目標(biāo)就是對(duì)于整個(gè)應(yīng)用來講,經(jīng)常要有一個(gè)中心地方來進(jìn)行日志的統(tǒng)一配置侵歇,包括所有的外部組件骂澄。比它更困難的可能是有太多的日志框架去選擇。
Spring中的強(qiáng)制日志依賴是Jakarta Commons Logging API (JCL)惕虑。我們編譯JCL并使JCL`log`對(duì)象對(duì)類是可見的坟冲,這擴(kuò)展了Spring框架磨镶。所有版本的Spring采用同一個(gè)日志庫:移植是容易的,因?yàn)榧词箲?yīng)用擴(kuò)展了Spring但保留了向后兼容性健提,這一點(diǎn)對(duì)用戶來說很重要琳猫。我們實(shí)現(xiàn)這個(gè)的方式是讓Spring的模塊之一顯式的依賴`commons-logging`(JCL的標(biāo)準(zhǔn)實(shí)現(xiàn)),然后使其它模塊在編譯時(shí)依賴這個(gè)模塊矩桂。例如如果你在使用Maven沸移,想找出依賴于`commons-logging`的依賴在哪,它在Spring中侄榴,更確切的說它是在Spring的中心模塊`spring-core`中雹锣。
關(guān)于`commons-logging`的一件好事是要使你的應(yīng)用工作你不需要任何其它的東西。它有一個(gè)運(yùn)行時(shí)發(fā)現(xiàn)算法癞蚕,這個(gè)算法能尋找其它的日志框架在知名的classpath中蕊爵,并使用一個(gè)它認(rèn)為是合適的(或者你告訴它你想用哪個(gè)如果你需要的話)。如果找不到任何別的你可以從JDK中找到一個(gè)非常美好漂亮的日志(java.util.logging或縮寫為JUL)桦山。在大多數(shù)環(huán)境中你可以發(fā)現(xiàn)你的Spring應(yīng)用恰當(dāng)?shù)剡\(yùn)行并輸出日志到控制臺(tái)輸出框中攒射,那是很重要的。
不使用Commons Logging
不幸的是恒水, 雖然`commons-logging`的運(yùn)行時(shí)發(fā)現(xiàn)算法對(duì)于終端用戶是方便的会放,但它是有問題的。如果我們將時(shí)鐘回?fù)芏ち瑁裇pring作為一個(gè)新項(xiàng)目重新開始咧最,將會(huì)選擇一個(gè)不同的日志依賴。第一個(gè)選擇可能是Simple Logging Facade for Java(SLF4J)御雕,應(yīng)用內(nèi)部使用Spring的人使用的許多其它工具也用了SLF4J矢沿。
這兒有兩種方式關(guān)掉`commons-logging`:
從
spring-core
模塊排除依賴(因?yàn)樗俏ㄒ坏娘@式依賴)commons-logging
的模塊-
依賴于一個(gè)特定的
commons-logging
依賴,用一個(gè)空jar替換這個(gè)依賴(更多細(xì)節(jié)可以在SLF4J FAQ中找到)酸纲。為了排除`commons-logging`捣鲸,把下面的內(nèi)容加入到你的`dependencyManagement`部分:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.0.BUILD-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
現(xiàn)在這個(gè)應(yīng)用可能是壞了的,因?yàn)樵赾lasspath中沒有JCL API的實(shí)現(xiàn)闽坡,為了解決這個(gè)問題必須提供一個(gè)新的實(shí)現(xiàn)栽惶。在接下來的部分我們將向你展示怎樣提供一個(gè)JCL替代實(shí)現(xiàn),使用SLF4J就是一個(gè)例子疾嗅。
使用SLF4J
SLF4J是一個(gè)更純凈的依賴并且在運(yùn)行時(shí)比`commons-logging`更有效外厂,因?yàn)樗褂镁幾g時(shí)綁定來代替運(yùn)行時(shí)查找集成的其它日志框架。這也意味著你必須更清楚你想要運(yùn)行時(shí)發(fā)生什么宪迟,然后相應(yīng)的聲明它或配置它酣衷。SLF4J提供跟許多常用日志框架的綁定交惯,因此你通炒卧螅可以選擇一個(gè)你正在使用的日志框架穿仪,然后綁定到配置和管理上。
SLF4J提供跟許多常用日志框架的綁定意荤,包括JCL啊片,它做的恰恰相反,建立其它日志框架和它自己的紐帶玖像。因此為了在Spring中使用SLF4J紫谷,你需要用SLF4J-JCL連接器取替換`commons-logging`依賴。一旦你在Spring內(nèi)部使用了日志調(diào)用捐寥,Spring會(huì)將日志調(diào)用變?yōu)檎{(diào)用SLF4J API笤昨,如果你應(yīng)用中其它的庫調(diào)用了那個(gè)API,你將有一個(gè)單獨(dú)的地方配置和管理日志握恳。
一個(gè)常用的選擇連接Spring和SLF4J瞒窒,然后提供SLF4J到Log4J的顯式綁定。你需要提供四個(gè)依賴(排除現(xiàn)有的`commons-logging`):連接乡洼、SLF4J API崇裁、到Log4J的綁定、Log4J本身的實(shí)現(xiàn)束昵。在Maven中你可能這么做:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.0.BUILD-SNAPSHOT</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`的關(guān)于類加載器的問題锹雏,尤其是你在一個(gè)像OSGi平臺(tái)那樣嚴(yán)格的容器中的時(shí)候巴比,它應(yīng)該更好操作。據(jù)說這兒也有一個(gè)性能提升逼侦,因?yàn)榻壎ㄊ窃诰幾g時(shí)而不是在運(yùn)行時(shí)匿辩。
在SLF4J用戶中,一個(gè)更通用的選擇是直接綁定到[Logback](http://logback.qos.ch/)榛丢,這樣使用步驟更少且依賴也更少铲球。這去除了外部綁定步驟,因?yàn)長ogback直接實(shí)現(xiàn)了SLF4J晰赞,因此你僅需要依賴兩個(gè)庫而不是四個(gè)(`jcl-over-slf4j`和`logback`)稼病。如果你這樣做的話你可能也需要從其它的外部應(yīng)用中(不是從Spring)排除slf4j-api依賴,因?yàn)槟阍赾lasspath中僅需要一個(gè)版本的API掖鱼。
使用Log4J
許多人使用Log4j作為配置和管理的日志框架然走。它有效且完善的,當(dāng)我們構(gòu)建和測(cè)試Spring時(shí)戏挡,實(shí)際上這就是在運(yùn)行時(shí)我們使用的東西芍瑞。Spring也提供一些配置和初始化Log4j的工具,因此在某些模塊有可選的Log4j的編譯時(shí)依賴褐墅。
為了使Log4j能與默認(rèn)的JCL依賴(`commons-logging`)一起工作拆檬,所有你需要做的是把Log4j放到classpath中洪己,并提供一個(gè)配置文件(`log4j.properties`或`log4j.xml`在classpath的根目錄)。對(duì)于Maven用戶依賴聲明如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
下面是一個(gè)log4j.properties輸出日志到控制臺(tái)的樣本:
運(yùn)行時(shí)容器使用本地化JCL
許多人在容器中運(yùn)行他們的Spring應(yīng)用竟贯,容器本身提供了一個(gè)JCL實(shí)現(xiàn)答捕。IBM Websphere Application Server (WAS) 是原型。這經(jīng)常會(huì)引起問題屑那,不幸的是沒有一勞永逸的解決方案拱镐;在大多數(shù)環(huán)境下簡(jiǎn)單的執(zhí)行`commons-logging`是不夠的。
為了使這個(gè)更清楚:報(bào)告的問題本質(zhì)上一般不是關(guān)于JCL的持际,或關(guān)于`commons-logging`的:而是他們?nèi)ソ壎╜commons-logging`到其它的框架上(通常是Log4j)沃琅。這可能會(huì)失敗因?yàn)閌commons-logging`在一些容器的舊版本(1.0)和大多數(shù)人使用的現(xiàn)代版本(1.1)中改變了運(yùn)行時(shí)發(fā)現(xiàn)方式。Spring不使用JCL API的和任何不常用的部分蜘欲,因此不會(huì)有問題出現(xiàn)阵难,但是一旦Spring或你的應(yīng)用試圖去輸出日志,你可能發(fā)現(xiàn)到Log4j的綁定是不起作用的芒填。
在這種情況下使用WAS最容易做的事是逆轉(zhuǎn)類加載層(IBM稱為"parent last")呜叫,為的是應(yīng)用能控制依賴,而不是容器殿衰。雖然這種選擇并非總是公開的朱庆,但在公共領(lǐng)域?qū)τ谔娲椒ㄓ性S多其它的建議,你的解決這個(gè)問題花的時(shí)間可能是不同的闷祥,這取決于確定的版本和容器集合的特性娱颊。
Part II. 核心技術(shù)
這部分參考文檔包含了所有完全集成到Spring框架中的那些技術(shù)。
在這些中最重要的是Spring框架的控制反轉(zhuǎn)(IoC)容器凯砍。對(duì)Spring框架IoC容器的徹底處理是緊隨其后的Spring面向切面編程(AOP)技術(shù)的全面覆蓋箱硕。Spring框架有它自己的AOP框架,這在概念上很容易理解悟衩,在Java企業(yè)級(jí)開發(fā)中成功了解決了AOP需求中80%的關(guān)鍵點(diǎn)剧罩。
Spring也提供了AspectJ的全面集成(目前是最豐富的-考慮到功能-并且確定在Java企業(yè)中是最成熟的AOP實(shí)現(xiàn))。
- Chapter 3, The IoC container
- Chapter 4, Resources
- Chapter 5, Validation, Data Binding, and Type Conversion
- Chapter 6, Spring Expression Language (SpEL)
- Chapter 7, Aspect Oriented Programming with Spring
- Chapter 8, Spring AOP APIs