文章作者:Tyan
博客:noahsnail.com
2.Introduction to the Spring Framework
The Spring Framework is a Java platform that provides comprehensive infrastructure support for developing Java applications. Spring handles the infrastructure so you can focus on your application.
Spring框架是一個為支持開發Java應用提供全面基礎架構的Java平臺。Spring處理基礎架構,因此你可以集中精力在你有應用上。
Spring enables you to build applications from "plain old Java objects" (POJOs) and to apply enterprise services non-invasively to POJOs. This capability applies to the Java SE programming model and to full and partial Java EE.
Spring使你能創建普通Java對象(POJO)并能非侵入式的將企業服務應用到普通Java對象(POJO)上。
Examples of how you, as an application developer, can benefit from the Spring platform:
- Make a Java method execute in a database transaction without having to deal with transaction APIs.
- Make a local Java method a remote procedure without having to deal with remote APIs.
- Make a local Java method a management operation without having to deal with JMX APIs.
- Make a local Java method a message handler without having to deal with JMS APIs.
作為一個應用開發者,下面是一些你能從Spring平臺受益的例子:
- 在一個數據庫業務中執行一個Java方法而不必處理業務APIs
- 使一個本地的Java方法可以遠程調用而不必處理遠程APIs
- 使一個本地Java方法變為管理操作而不必處理JMX APIs
- 使一個本地Java方法變為消息處理器而不必處理JMS APIs
2.1 Dependency Injection and Inversion of Control
A Java application?—?a loose term that runs the gamut from constrained, embedded applications to n-tier, server-side enterprise applications?—?typically consists of objects that collaborate to form the application proper. Thus the objects in an application have dependencies on each other.
Java應用——一個不精確的術語,既可以表示受限制的嵌入式應用又可以表示N層服務端的企業級應用——通常由許多對象構成,這些對象協作形成完整的應用程序。因此一個應用程序中的對象是相互依賴的。
Although the Java platform provides a wealth of application development functionality, it lacks the means to organize the basic building blocks into a coherent whole, leaving that task to architects and developers. Although you can use design patterns such as Factory, Abstract Factory, Builder, Decorator, and Service Locator to compose the various classes and object instances that make up an application, these patterns are simply that: best practices given a name, with a description of what the pattern does, where to apply it, the problems it addresses, and so forth. Patterns are formalized best practices that you must implement yourself in your application.
盡管Java平臺提供了大量的應用開發功能,但是它缺少把這些基本構建模塊組織成一個連貫整體的方法,并把組織基本構建模塊的任務留給了架構師和開發者。雖然你可以使用設計模式例如工廠模式、抽象工廠模式、生成器模式、裝飾模式、服務定位模式來創建構成應用的各種類和對象實例,但這些設計模式很簡單:命名的最佳方法、模式的作用描述、應用模式的位置、模式解決的問題等等。模式使最佳實踐形式化了,這意味著你必須在你的應用中自己實現它。
The Spring Framework Inversion of Control (IoC) component addresses this concern by providing a formalized means of composing disparate components into a fully working application ready for use. The Spring Framework codifies formalized design patterns as first-class objects that you can integrate into your own application(s). Numerous organizations and institutions use the Spring Framework in this manner to engineer robust, maintainable applications.
Spring框架中的控制反轉(IoC)組件通過提供一種形式化方法解決了這個問題,這個形式化方法將不同的組件創建到一個隨時可用的完整的工作應用中。Spring框架將形式化的設計模式編碼成了你可以集成到你自己的應用中的最好對象。許多組織和機構用這種方式應用Spring框架來構建魯棒的、可維護的應用。
Background
"The question is, what aspect of control are [they] inverting?" Martin Fowler posed this question about Inversion of Control (IoC) on his site in 2004. Fowler suggested renaming the principle to make it more self-explanatory and came up with Dependency Injection.
?
背景
"問題是什么是控制反轉?" 2004年Martin Fowler在他的網站上提出了這個關于控制反轉(IoC)問題。Fowler建議重新命名這個原理使它更一目了然并且提出了依賴注入。
2.2 Modules
The Spring Framework consists of features organized into about 20 modules. These modules are grouped into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented Programming), Instrumentation, Messaging, and Test, as shown in the following diagram.
Spring框架包含的功能大約由20個模塊組成。這些模塊按組可分為核心容器、數據訪問/集成,Web,AOP(面向切面編程)、設備、消息和測試,如下圖所示。
Figure 2.1. Overview of the Spring Framework
The following sections list the available modules for each feature along with their artifact names and the topics they cover. Artifact names correlate to artifact IDs used in Dependency Management tools.
接下來的章節列出了每個功能可用的模塊、它們的工件名字以及它們包含的主題。工件名字與依賴管理工具中使用的artifact IDs有關。
2.2.1 Core Container
The Core Container consists of the spring-core
, spring-beans
, spring-context
, spring-context-support
, and spring-expression
(Spring Expression Language) modules.
核心容器功能包括spring-core
, spring-beans
, spring-context
, spring-context-support
, and spring-expression
(Spring表現語言)模塊。
The spring-core
and spring-beans
modules provide the fundamental parts of the framework, including the IoC and Dependency Injection features. The BeanFactory
is a sophisticated implementation of the factory pattern. It removes the need for programmatic singletons and allows you to decouple the configuration and specification of dependencies from your actual program logic.
spring-core
和spring-beans
模塊提供了框架的基礎結構部分,包含控制反轉(IoC)和依賴注入(DI)功能。BeanFactory
是工廠模式的高級實現。它去掉了程序單例模式的需求并且允許你從實際的程序邏輯中解耦配置和依賴關系。
The Context (spring-context
) module builds on the solid base provided by the Core and Beans modules: it is a means to access objects in a framework-style manner that is similar to a JNDI registry. The Context module inherits its features from the Beans module and adds support for internationalization (using, for example, resource bundles), event propagation, resource loading, and the transparent creation of contexts by, for example, a Servlet container. The Context module also supports Java EE features such as EJB, JMX, and basic remoting. The ApplicationContext
interface is the focal point of the Context module.spring-context-support
provides support for integrating common third-party libraries into a Spring application context, in particular for caching (EhCache, JCache) and scheduling (CommonJ, Quartz).
上下文(spring-context
)模塊建立在由Core模塊和Beans模塊提供的堅實基礎上:它是在類似于JNDI注冊表式的框架風格模式中訪問對象的一種方法。上下文模塊繼承了Beans模塊的功能,并添加了對國際化(例如使用資源捆綁)、事件傳播、資源加載和上下文透明創建(例如通過Servlet容器)的支持。上下文模塊也支持Java EE功能例如EJB,JMX和基本的遠程。ApplicationContext
接口是上下文模塊的焦點。spring-context-support
支持將第三方庫集成進Spring應用程序上下文中,特別是緩存(EhCache, JCache)和定時執行(CommonJ, Quartz)。
The spring-expression
module provides a powerful Expression Language for querying and manipulating an object graph at runtime. It is an extension of the unified expression language (unified EL) as specified in the JSP 2.1 specification. The language supports setting and getting property values, property assignment, method invocation, accessing the content of arrays, collections and indexers, logical and arithmetic operators, named variables, and retrieval of objects by name from Spring’s IoC container. It also supports list projection and selection as well as common list aggregations.
spring-expression
模塊提供了強大的表達式語言用來在運行時查詢和操作對象圖。它是JSP 2.1規范中統一表達式語言(unified EL)的擴展。這個語言支持setting和getting屬性值,屬性分配,方法調用,訪問數組、集合和索引器的內容,邏輯和算術操作,變量命名,從Spring Ioc容器中通過名字檢索對象。它也支持它還支持列表投影、選擇以及常見的列表聚合。
2.2.2 AOP and Instrumentation
The spring-aop
module provides an AOP Alliance-compliant aspect-oriented programming implementation allowing you to define, for example, method interceptors and pointcuts to cleanly decouple code that implements functionality that should be separated. Using source-level metadata functionality, you can also incorporate behavioral information into your code, in a manner similar to that of .NET attributes.
spring-aop
模塊提供了AOP Alliance-compliant(AOP聯盟)面向切面編程的實現,例如允許你自定義方法攔截器和切入點來清晰的解耦功能實現上應該分開的代碼。使用源碼級的元數據功能,你也可以將行為信息合并到你的代碼中,在某種程度上這類似于.NET的屬性值。
The separate spring-aspects
module provides integration with AspectJ.
獨立的spring-aspects
模塊提供了與AspectJ的集成。
The spring-instrument
module provides class instrumentation support and classloader implementations to be used in certain application servers. The spring-instrument-tomcat
module contains Spring’s instrumentation agent for Tomcat.
spring-instrument
模塊提供了類設備支持和類加載器的實現,它們可以在某些應用服務器中使用。spring-instrument-tomcat
模塊包含了Tomcat的Spring設備代理。
2.2.3 Messaging
Spring Framework 4 includes a spring-messaging
module with key abstractions from the Spring Integration project such as Message
, MessageChannel
, MessageHandler
, and others to serve as a foundation for messaging-based applications. The module also includes a set of annotations for mapping messages to methods, similar to the Spring MVC annotation based programming model.
Spring 4框架中包含了spring-messaging
模塊,它對Spring集成項目例如Message
, MessageChannel
, MessageHandler
和其它作為消息應用服務基礎的項目進行了重要的抽象。這個模塊也包含了一系列將消息映射到方法上的注解,這個注解與基于編程模型Spring MVC注解類似。
2.2.4 Data Access/Integration
The Data Access/Integration layer consists of the JDBC, ORM, OXM, JMS, and Transaction modules.
數據訪問/集成層包括JDBC,ORM,OXM,JMS和業務模塊。
The spring-jdbc
module provides a JDBC-abstraction layer that removes the need to do tedious JDBC coding and parsing of database-vendor specific error codes.
spring-jdbc
模塊提供了JDBC抽象層,不需要再編寫單調的JDBC代碼,解析數據庫提供商指定的錯誤編碼。
The spring-tx
module supports programmatic and declarative transaction management for classes that implement special interfaces and for all your POJOs (Plain Old Java Objects).
spring-tx
模塊為實現指定接口和所有的普通Java對象(POJOs)的類提供編程式(programmatic)和聲明式(declarative)的業務管理。
The spring-orm
module provides integration layers for popular object-relational mapping APIs, including JPA and Hibernate. Using the spring-orm
module you can use these O/R-mapping frameworks in combination with all of the other features Spring offers, such as the simple declarative transaction management feature mentioned previously.
spring-orm
模塊提供流行的對象關系映射APIs的集成層,包括JPA和Hibernate。在使用spring-orm
模塊時,你可以將Spring的其它功能與這些O/R-mapping框架結合起來使用,例如前面提到的簡單聲明式業務管理的功能。
The spring-oxm
module provides an abstraction layer that supports Object/XML mapping implementations such as JAXB, Castor, JiBX and XStream.
spring-oxm
模塊提供對Object/XML映射實現例如JAXB,Castor,JiBx和XStream的抽象層。
The spring-jms
module (Java Messaging Service) contains features for producing and consuming messages. Since Spring Framework 4.1, it provides integration with the spring-messaging
module.
spring-jms
模塊(Java消息服務)包含產生和處理消息的功能。從Spring 4.1框架開始它提供了與spring-messaging
的集成。
2.2.5 Web
The Web layer consists of the spring-web
, spring-webmvc
and spring-websocket
modules.
網絡層包含spring-web
, spring-webmvc
和spring-websocket
模塊。
The spring-web
module provides basic web-oriented integration features such as multipart file upload functionality and the initialization of the IoC container using Servlet listeners and a web-oriented application context. It also contains an HTTP client and the web-related parts of Spring’s remoting support.
spring-web
模塊提供基本的面向網絡集成功能,例如multipart文件上傳功能,使用Servlet監聽器來初始化Ioc容器和面向網絡的應用程序上下文。它也包含了HTTP客戶端和Spring遠程支持中網絡相關的部分。
The spring-webmvc
module (also known as the Web-Servlet module) contains Spring’s model-view-controller (MVC) and REST Web Services implementation for web applications. Spring’s MVC framework provides a clean separation between domain model code and web forms and integrates with all of the other features of the Spring Framework.
spring-webmvc
模塊(也被稱為Web-Servlet模塊)包含了Spring的model-view-controller(MVC)和REST Web Services的網絡應用實現。Spring的MVC框架提供了對領域模型代碼,web表單,Spring框架其他功能的完全分離。
2.2.6 Test
The spring-test
module supports the unit testing and integration testing of Spring components with JUnit or TestNG. It provides consistent loading of Spring ApplicationContexts
and caching of those contexts. It also provides mock objects that you can use to test your code in isolation.
spring-test
模塊支持單元測試,Spring組件和JUnit或TestNG的集成測試。它提供了Spring的ApplicationContexts
加載和這些上下文緩存的一致。它也提供了可以單獨測試代碼的模擬對象。
2.3 Usage scenarios
The building blocks described previously make Spring a logical choice in many scenarios, from embedded applications that run on resource-constrained devices to full-fledged enterprise applications that use Spring’s transaction management functionality and web framework integration.
前面描述的搭積木方式使Spring在許多場景中都有一個合理選擇,從運行在資源受限的嵌入式應用到全面成熟的企業級應用都在使用Spring的業務管理功能和網絡框架集成。
Figure 2.2. Typical full-fledged Spring web application
Spring’s declarative transaction management features make the web application fully transactional, just as it would be if you used EJB container-managed transactions. All your custom business logic can be implemented with simple POJOs and managed by Spring’s IoC container. Additional services include support for sending email and validation that is independent of the web layer, which lets you choose where to execute validation rules. Spring’s ORM support is integrated with JPA and Hibernate; for example, when using Hibernate, you can continue to use your existing mapping files and standard Hibernate SessionFactory
configuration. Form controllers seamlessly integrate the web-layer with the domain model, removing the need for ActionForms
or other classes that transform HTTP parameters to values for your domain model.
Spring的聲明式業務管理功能使web應用全面的業務化,如果你用過EJB容器管理業務的話你會發現它們基本一樣。你所有自定義的業務邏輯都可以用POJOs實現并通過Spring的IoC容器管理。附加業務包括支持郵件發送和驗證,這個是獨立于web層之外的,你可以自由選擇驗證規則執行的位置。Spring對ORM的支持與JPA和Hibernate進行了集成;例如,當你使用Hibernate時,你可以繼續使用你現有的映射文件和標準的Hibernate SessionFactory
配置。表單控制器被無縫的將web層和領域模型進行了集成,對于你的領域模型來講不再需要ActionForms
或其它的將HTTP參數轉換成值的
Figure 2.3. Spring middle-tier using a third-party web framework
Sometimes circumstances do not allow you to completely switch to a different framework. The Spring Framework does not force you to use everything within it; it is not an all-or-nothing solution. Existing front-ends built with Struts, Tapestry, JSF or other UI frameworks can be integrated with a Spring-based middle-tier, which allows you to use Spring transaction features. You simply need to wire up your business logic using an ApplicationContext
and use a WebApplicationContext
to integrate your web layer.
有時候環境不允許你完全轉成一個不同的框架。Spring框架不強迫你都采用它內部的東西;它不是一個要么全有要么全無的解決方案。現有的采用Struts,Tapestry,JSF或其它UI框架構建的前端可以與基于Spring的中間層進行集成,這可以讓你使用Spring的業務功能。你只需要簡單的用ApplicationContext
和WebApplicationContext
綁定你的業務邏輯然后集成到web層即可。
Figure 2.4. Remoting usage scenario
When you need to access existing code through web services, you can use Spring’s Hessian-
, Rmi-
or HttpInvokerProxyFactoryBean
classes. Enabling remote access to existing applications is not difficult.
當你需要通過web服務訪問現有代碼時,你可以使用Spring的Hessian-
, Rmi-
或 HttpInvokerProxyFactoryBean
類。這能讓遠程訪問現有應用變得很容易。
Figure 2.5. EJBs - Wrapping existing POJOs
The Spring Framework also provides an access and abstraction layer for Enterprise JavaBeans, enabling you to reuse your existing POJOs and wrap them in stateless session beans for use in scalable, fail-safe web applications that might need declarative security.
Spring框架也為企業JavaBeans提供了訪問和抽象層,使你能重用你現有的POJOs,為了可擴展使用可以將它們包裝成無狀態的session beans,自動防故障的web應用可能需要聲明安全。
2.3.1 Dependency Management and Naming Conventions
Dependency management and dependency injection are different things. To get those nice features of Spring into your application (like dependency injection) you need to assemble all the libraries needed (jar files) and get them onto your classpath at runtime, and possibly at compile time. These dependencies are not virtual components that are injected, but physical resources in a file system (typically). The process of dependency management involves locating those resources, storing them and adding them to classpaths. Dependencies can be direct (e.g. my application depends on Spring at runtime), or indirect (e.g. my application depends on commons-dbcp
which depends on commons-pool
). The indirect dependencies are also known as "transitive" and it is those dependencies that are hardest to identify and manage.
依賴管理和依賴注入是完全不同的兩件事。為了能你的應用中使用Spring的優秀特性(像依賴注入),你需要收集所有必要的庫(jar文件)并在運行時將它們添加到classpath中,有可能在編譯時就需要添加。這些依賴不是要被注入的虛擬組建,而是文件系統中的物理資源(通常情況下)。這些依賴管理的過程包括資源的定位、存儲和添加到classpath中。依賴可以是直接的(例如:我的應用在運行時依賴Spring),或間接的(例如:我的應用依賴commons-dbcp
,而它依賴commons-pool
)。間接依賴也被稱為"傳遞式"的,這些依賴也是最難識別和管理的。
If you are going to use Spring you need to get a copy of the jar libraries that comprise the pieces of Spring that you need. To make this easier Spring is packaged as a set of modules that separate the dependencies as much as possible, so for example if you don’t want to write a web application you don’t need the spring-web modules. To refer to Spring library modules in this guide we use a shorthand naming convention spring-*
or spring-*.jar
, where *
represents the short name for the module (e.g. spring-core
, spring-webmvc
, spring-jms
, etc.). The actual jar file name that you use is normally the module name concatenated with the version number (e.g. spring-core-5.0.0.BUILD-SNAPSHOT.jar
).
如果你想使用Spring,你需要有包含你需要的Spirng功能的jar庫副本。為了使這個更容易,Spring被打包成了一系列盡可能將依賴分離開的模塊,例如你不想寫web應用那你就不需要spring-web模塊。為了在本指南中談及Spring的庫模塊,我們使用了一個簡寫命名約定spring-*
或spring-*.jar
,*
表示模塊的簡寫名字(例如spring-core
, spring-webmvc
, spring-jms
等等)。實際中你使用的jar文件名字通常是模塊名加上版本號(例如spring-core-5.0.0.BUILD-SNAPSHOT.jar
)。
Each release of the Spring Framework will publish artifacts to the following places:
- Maven Central, which is the default repository that Maven queries, and does not require any special configuration to use. Many of the common libraries that Spring depends on also are available from Maven Central and a large section of the Spring community uses Maven for dependency management, so this is convenient for them. The names of the jars here are in the form
spring-*-<version>.jar
and the Maven groupId isorg.springframework
. - In a public Maven repository hosted specifically for Spring. In addition to the final GA releases, this repository also hosts development snapshots and milestones. The jar file names are in the same form as Maven Central, so this is a useful place to get development versions of Spring to use with other libraries deployed in Maven Central. This repository also contains a bundle distribution zip file that contains all Spring jars bundled together for easy download.
So the first thing you need to decide is how to manage your dependencies: we generally recommend the use of an automated system like Maven, Gradle or Ivy, but you can also do it manually by downloading all the jars yourself.
Spring框架的每次發布都會下面的地方公布artifacts:
- Maven Central,Maven查詢的默認倉庫,使用時不需要任何特定的配置。Spring依賴的許多共通庫也可以從Maven Central獲得,Spring社區的很大一部分都在使用Maven進行依賴管理,因此這對他們來說是很方便的。jar包的命名形式是
spring-*-<version>.jar
,Maven GroupId是org.springframework
。 - 由Spring掌管的公開Maven庫。除了最終的GA release(公開可獲得的版本)之外,這個倉庫也有開發版本的快照和milestone版本。jar包的命名形式和Maven Central一樣,這是一個可以使用Spring開發版本有用地方,而其它的庫部署在Maven Central。這個庫也包含的捆綁分布的zip文件,這個zip文件中所有的Spring jar包被捆綁到一起很容易下載。
You will find bellow the list of Spring artifacts. For a more complete description of each modules, see Section 2.2, “Modules”.
你將在下面找到Spring artifacts列表。想要每個模塊更全面的描述,請看2.2小節。
Table 2.1. Spring Framework Artifacts
Spring Dependencies and Depending on Spring
Although Spring provides integration and support for a huge range of enterprise and other external tools, it intentionally keeps its mandatory dependencies to an absolute minimum: you shouldn’t have to locate and download (even automatically) a large number of jar libraries in order to use Spring for simple use cases. For basic dependency injection there is only one mandatory external dependency, and that is for logging (see below for a more detailed description of logging options).
雖然Spring提供集成并支持大范圍內的企業和其它外部工具,但它有意使它的強制性依賴到一個絕對最小化的程度:對于簡單的用例你不應該為了使用Spring而定位和下載(即使是自動的)許多jar庫。對于基本的依賴注入僅有一個強制性的外部依賴,那個依賴是關于日志的(在下面可以看到日志選擇更詳細的描述)。
Next we outline the basic steps needed to configure an application that depends on Spring, first with Maven and then with Gradle and finally using Ivy. In all cases, if anything is unclear, refer to the documentation of your dependency management system, or look at some sample code - Spring itself uses Gradle to manage dependencies when it is building, and our samples mostly use Gradle or Maven.
接下來我們概述配置一個依賴于Spring的應用需要的基本步驟,首先Maven的,其次是Gradle的,最后是Ivy的。在所有的案例中,如果有任何不清楚的地方,請參考你的依賴管理系統的文檔,或者看一些示例代碼——Spring本身構建時使用Gradle來管理依賴,我們例子中大多數是使用Gradle和Maven的。
Maven Dependency Management
If you are using Maven for dependency management you don’t even need to supply the logging dependency explicitly. For example, to create an application context and use dependency injection to configure an application, your Maven dependencies will look like this:
如果你正在使用Maven來進行依賴管理,那你不必顯式的提供日志依賴。例如,為了創建一個應用上下文,使用依賴注入來配置一個應用,你的Maven依賴看上去是這樣的:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.0.BUILD-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
</dependencies>
That’s it. Note the scope can be declared as runtime if you don’t need to compile against Spring APIs, which is typically the case for basic dependency injection use cases.
就是它。注意如果你不需要編譯Spring APIs,scope可以被聲明成rumtime,這是典型的基本依賴注入的情況。
The example above works with the Maven Central repository. To use the Spring Maven repository (e.g. for milestones or developer snapshots), you need to specify the repository location in your Maven configuration. For full releases:
上面的例子是采用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>
For milestones:
對于milestone版本:
<repositories>
<repository>
<id>io.spring.repo.maven.milestone</id>
<url>http://repo.spring.io/milestone/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
And for snapshots:
對于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 "Bill Of Materials" Dependency
It is possible to accidentally mix different versions of Spring JARs when using Maven. For example, you may find that a third-party library, or another Spring project, pulls in a transitive dependency to an older release. If you forget to explicitly declare a direct dependency yourself, all sorts of unexpected issues can arise.
在使用Maven時,有可能會偶然的將不同版本的Spring JARs混合起來。例如,你可能找到一個第三方庫,或另一個Spring項目,通過傳遞依賴進入了一個更舊的版本。如果你忘了自己顯式的聲明一個直接依賴,會產生各種意想不到的問題。
To overcome such problems Maven supports the concept of a "bill of materials" (BOM) dependency. You can import the spring-framework-bom
in your dependencyManagement
section to ensure that all spring dependencies (both direct and transitive) are at the same version.
為了解決這種問題,Maven支持"材料清單"(BOM)依賴的概念。你可以在你的dependencyManagement
部分導入spring-framework-bom
來確保所有的Spring依賴(直接和傳遞的)都是同一個版本。
<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>
An added benefit of using the BOM is that you no longer need to specify the <version>
attribute when depending on Spring Framework artifacts:
使用BOM的額外好處是當依賴Spring框架的artifacts時你不再需要指定<version>
屬性:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependencies>
Gradle Dependency Management
To use the Spring repository with the Gradle build system, include the appropriate URL in the repositories
section:
為了在Gradle構建系統中使用Spring倉庫,在repositories
部分需要包含合適的URL:
repositories {
mavenCentral()
// and optionally...
maven { url "http://repo.spring.io/release" }
}
You can change the repositories
URL from /release
to /milestone
or /snapshot
as appropriate. Once a repository has been configured, you can declare dependencies in the usual Gradle way:
當合適的時候你可以修改repositories
的URL從/release
到/milestone
或/snapshot
。一旦一個倉庫被配置了,你可以用通常的Gradle方式聲明依賴:
dependencies {
compile("org.springframework:spring-context:5.0.0.BUILD-SNAPSHOT")
testCompile("org.springframework:spring-test:5.0.0.BUILD-SNAPSHOT")
}
Ivy Dependency Management
If you prefer to use Ivy to manage dependencies then there are similar configuration options.
如果你更喜歡使用Ivy來管理依賴,這有類似的配置選擇。
To configure Ivy to point to the Spring repository add the following resolver to your ivysettings.xml
:
為了配置Ivy指定Spring倉庫,添加下面的解析器到你的ivysettings.xml
:
<resolvers>
<ibiblio name="io.spring.repo.maven.release"
m2compatible="true"
root="http://repo.spring.io/release/"/>
</resolvers>
You can change the root URL from /release/
to /milestone/
or /snapshot/
as appropriate.
當合適的時候你可以更改根URL從repositories
的URL從/release
到/milestone
或/snapshot
。
Once configured, you can add dependencies in the usual way. For example (in ivy.xml
):
一旦配置了,你可以通過一般的方式添加依賴。例如(在ivy.xml
):
<dependency org="org.springframework"
name="spring-core" rev="5.0.0.BUILD-SNAPSHOT" conf="compile->runtime"/>
Distribution Zip Files
Although using a build system that supports dependency management is the recommended way to obtain the Spring Framework, it is still possible to download a distribution zip file.
盡管使用一個支持依賴管理的構建系統是獲得Spring框架的推薦方式,但仍然可以下載發行版的Zip文件。
Distribution zips are published to the Spring Maven Repository (this is just for our convenience, you don’t need Maven or any other build system in order to download them).
發行版的zips是被發布到Spring Maven倉庫(這只是為了我們的方便,為了下載它們你不需要Maven或任何其它的構建系統)。
To download a distribution zip open a web browser to http://repo.spring.io/release/org/springframework/spring and select the appropriate subfolder for the version that you want. Distribution files end -dist.zip
, for example spring-framework-{spring-version}-RELEASE-dist.zip. Distributions are also published for milestones and snapshots.
為了下載發行版zip,打開瀏覽器輸入http://repo.spring.io/release/org/springframework/spring,然后選擇你想要的版本的合適子文件夾。發行版文件以-dist.zip
結尾,例如spring-framework-{spring-version}-RELEASE-dist.zip。發行版也可以公布milestone版本或snapshots版本。
2.3.2 Logging
Logging is a very important dependency for Spring because a) it is the only mandatory external dependency, b) everyone likes to see some output from the tools they are using, and c) Spring integrates with lots of other tools all of which have also made a choice of logging dependency. One of the goals of an application developer is often to have unified logging configured in a central place for the whole application, including all external components. This is more difficult than it might have been since there are so many choices of logging framework.
日志對于Spring來說是一個非常重要的依賴,因為:a)它是唯一的強制性外部依賴,b)每個人都喜歡從他們使用的工具中看到一些輸出,c)Spring集成了許多其它的工具,這些工具也選擇了日志依賴。應用開發者的一個目標就是對于整個應用來講,經常要有一個中心地方來進行日志的統一配置,包括所有的外部組件。比它更困難的可能是有太多的日志框架去選擇。
The mandatory logging dependency in Spring is the Jakarta Commons Logging API (JCL). We compile against JCL and we also make JCL Log
objects visible for classes that extend the Spring Framework. It’s important to users that all versions of Spring use the same logging library: migration is easy because backwards compatibility is preserved even with applications that extend Spring. The way we do this is to make one of the modules in Spring depend explicitly on commons-logging
(the canonical implementation of JCL), and then make all the other modules depend on that at compile time. If you are using Maven for example, and wondering where you picked up the dependency on commons-logging
, then it is from Spring and specifically from the central module called spring-core
.
Spring中的強制日志依賴是Jakarta Commons Logging API (JCL)。我們編譯JCL并使JCLlog
對象對類是可見的,這擴展了Spring框架。所有版本的Spring采用同一個日志庫:移植是容易的,因為即使應用擴展了Spring但保留了向后兼容性,這一點對用戶來說很重要。我們實現這個的方式是讓Spring的模塊之一顯式的依賴commons-logging
(JCL的標準實現),然后使其它模塊在編譯時依賴這個模塊。例如如果你在使用Maven,想找出依賴于commons-logging
的依賴在哪,它在Spring中,更確切的說它是在Spring的中心模塊spring-core
中。
The nice thing about commons-logging
is that you don’t need anything else to make your application work. It has a runtime discovery algorithm that looks for other logging frameworks in well known places on the classpath and uses one that it thinks is appropriate (or you can tell it which one if you need to). If nothing else is available you get pretty nice looking logs just from the JDK (java.util.logging or JUL for short). You should find that your Spring application works and logs happily to the console out of the box in most situations, and that’s important.
關于commons-logging
的一件好事是要使你的應用工作你不需要任何其它的東西。它有一個運行時發現算法,這個算法能尋找其它的日志框架在知名的classpath中,并使用一個它認為是合適的(或者你告訴它你想用哪個如果你需要的話)。如果找不到任何別的你可以從JDK中找到一個非常美好漂亮的日志(java.util.logging或縮寫為JUL)。在大多數環境中你可以發現你的Spring應用恰當地運行并輸出日志到控制臺輸出框中,那是很重要的。
Not Using Commons Logging
Unfortunately, the runtime discovery algorithm in commons-logging
, while convenient for the end-user, is problematic. If we could turn back the clock and start Spring now as a new project it would use a different logging dependency. The first choice would probably be the Simple Logging Facade for Java ( SLF4J), which is also used by a lot of other tools that people use with Spring inside their applications.
不幸的是, 雖然commons-logging
的運行時發現算法對于終端用戶是方便的,但它是有問題的。如果我們將時鐘回撥,把Spring作為一個新項目重新開始,將會選擇一個不同的日志依賴。第一個選擇可能是Simple Logging Facade for Java(SLF4J),應用內部使用Spring的人使用的許多其它工具也用了SLF4J。
There are basically two ways to switch off commons-logging
:
- Exclude the dependency from the
spring-core
module (as it is the only module that explicitly depends oncommons-logging
) - Depend on a special commons-logging dependency that replaces the library with an empty jar (more details can be found in the SLF4J FAQ)
這兒有兩種方式關掉commons-logging
:
- 從
spring-core
模塊排除依賴(因為它是唯一的顯式依賴)commons-logging
的模塊 - 依賴于一個特定的
commons-logging
依賴,用一個空jar替換這個依賴(更多細節可以在SLF4J FAQ中找到)。
To exclude commons-logging
, add the following to your dependencyManagement
section:
為了排除commons-logging
,把下面的內容加入到你的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>
Now this application is probably broken because there is no implementation of the JCL API on the classpath, so to fix it a new one has to be provided. In the next section we show you how to provide an alternative implementation of JCL using SLF4J as an example.
現在這個應用可能是壞了的,因為在classpath中沒有JCL API的實現,為了解決這個問題必須提供一個新的實現。在接下來的部分我們將向你展示怎樣提供一個JCL替代實現,使用SLF4J就是一個例子。
Using SLF4J
SLF4J is a cleaner dependency and more efficient at runtime than commons-logging
because it uses compile-time bindings instead of runtime discovery of the other logging frameworks it integrates. This also means that you have to be more explicit about what you want to happen at runtime, and declare it or configure it accordingly. SLF4J provides bindings to many common logging frameworks, so you can usually choose one that you already use, and bind to that for configuration and management.
SLF4J是一個更純凈的依賴并且在運行時比commons-logging
更有效,因為它使用編譯時綁定來代替運行時查找集成的其它日志框架。這也意味著你必須更清楚你想要運行時發生什么,然后相應的聲明它或配置它。SLF4J提供跟許多常用日志框架的綁定,因此你通常可以選擇一個你正在使用的日志框架,然后綁定到配置和管理上。
SLF4J provides bindings to many common logging frameworks, including JCL, and it also does the reverse: bridges between other logging frameworks and itself. So to use SLF4J with Spring you need to replace the commons-logging
dependency with the SLF4J-JCL bridge. Once you have done that then logging calls from within Spring will be translated into logging calls to the SLF4J API, so if other libraries in your application use that API, then you have a single place to configure and manage logging.
SLF4J提供跟許多常用日志框架的綁定,包括JCL,它做的恰恰相反,建立其它日志框架和它自己的紐帶。因此為了在Spring中使用SLF4J,你需要用SLF4J-JCL連接器取替換commons-logging
依賴。一旦你在Spring內部使用了日志調用,Spring會將日志調用變為調用SLF4J API,如果你應用中其它的庫調用了那個API,你將有一個單獨的地方配置和管理日志。
A common choice might be to bridge Spring to SLF4J, and then provide explicit binding from SLF4J to Log4J. You need to supply 4 dependencies (and exclude the existing commons-logging
): the bridge, the SLF4J API, the binding to Log4J, and the Log4J implementation itself. In Maven you would do that like this
一個常用的選擇連接Spring和SLF4J,然后提供SLF4J到Log4J的顯式綁定。你需要提供四個依賴(排除現有的commons-logging
):連接、SLF4J API、到Log4J的綁定、Log4J本身的實現。在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>
That might seem like a lot of dependencies just to get some logging. Well it is, but it is optional, and it should behave better than the vanilla commons-logging
with respect to classloader issues, notably if you are in a strict container like an OSGi platform. Allegedly there is also a performance benefit because the bindings are at compile-time not runtime.
這可能看起來為了得到一些日志需要很多依賴。還好它是可選的,比起commons-logging
的關于類加載器的問題,尤其是你在一個像OSGi平臺那樣嚴格的容器中的時候,它應該更好操作。據說這兒也有一個性能提升,因為綁定是在編譯時而不是在運行時。
A more common choice amongst SLF4J users, which uses fewer steps and generates fewer dependencies, is to bind directly to Logback. This removes the extra binding step because Logback implements SLF4J directly, so you only need to depend on two libraries not four ( jcl-over-slf4j
and logback
). If you do that you might also need to exclude the slf4j-api dependency from other external dependencies (not Spring), because you only want one version of that API on the classpath.
在SLF4J用戶中,一個更通用的選擇是直接綁定到Logback,這樣使用步驟更少且依賴也更少。這去除了外部綁定步驟,因為Logback直接實現了SLF4J,因此你僅需要依賴兩個庫而不是四個(jcl-over-slf4j
和logback
)。如果你這樣做的話你可能也需要從其它的外部應用中(不是從Spring)排除slf4j-api依賴,因為你在classpath中僅需要一個版本的API。
Using Log4J
Many people use Log4j as a logging framework for configuration and management purposes. It’s efficient and well-established, and in fact it’s what we use at runtime when we build and test Spring. Spring also provides some utilities for configuring and initializing Log4j, so it has an optional compile-time dependency on Log4j in some modules.
許多人使用Log4j作為配置和管理的日志框架。它有效且完善的,當我們構建和測試Spring時,實際上這就是在運行時我們使用的東西。Spring也提供一些配置和初始化Log4j的工具,因此在某些模塊有可選的Log4j的編譯時依賴。
To make Log4j work with the default JCL dependency (commons-logging
) all you need to do is put Log4j on the classpath, and provide it with a configuration file ( log4j.properties
or log4j.xml
in the root of the classpath). So for Maven users this is your dependency declaration:
為了使Log4j能與默認的JCL依賴(commons-logging
)一起工作,所有你需要做的是把Log4j放到classpath中,并提供一個配置文件(log4j.properties
或log4j.xml
在classpath的根目錄)。對于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>
And here’s a sample log4j.properties for logging to the console:
下面是一個log4j.properties輸出日志到控制臺的樣本:
Runtime Containers with Native JCL
Many people run their Spring applications in a container that itself provides an implementation of JCL. IBM Websphere Application Server (WAS) is the archetype. This often causes problems, and unfortunately there is no silver bullet solution; simply excluding commons-logging
from your application is not enough in most situations.
許多人在容器中運行他們的Spring應用,容器本身提供了一個JCL實現。IBM Websphere Application Server (WAS) 是原型。這經常會引起問題,不幸的是沒有一勞永逸的解決方案;在大多數環境下簡單的執行commons-logging
是不夠的。
To be clear about this: the problems reported are usually not with JCL per se, or even with commons-logging
: rather they are to do with binding commons-logging
to another framework (often Log4J). This can fail because commons-logging
changed the way they do the runtime discovery in between the older versions (1.0) found in some containers and the modern versions that most people use now (1.1). Spring does not use any unusual parts of the JCL API, so nothing breaks there, but as soon as Spring or your application tries to do any logging you can find that the bindings to Log4J are not working.
為了使這個更清楚:報告的問題本質上一般不是關于JCL的,或關于commons-logging
的:而是他們去綁定commons-logging
到其它的框架上(通常是Log4j)。這可能會失敗因為commons-logging
在一些容器的舊版本(1.0)和大多數人使用的現代版本(1.1)中改變了運行時發現方式。Spring不使用JCL API的和任何不常用的部分,因此不會有問題出現,但是一旦Spring或你的應用試圖去輸出日志,你可能發現到Log4j的綁定是不起作用的。
In such cases with WAS the easiest thing to do is to invert the class loader hierarchy (IBM calls it "parent last") so that the application controls the JCL dependency, not the container. That option isn’t always open, but there are plenty of other suggestions in the public domain for alternative approaches, and your mileage may vary depending on the exact version and feature set of the container.
在這種情況下使用WAS最容易做的事是逆轉類加載層(IBM稱為"parent last"),為的是應用能控制依賴,而不是容器。雖然這種選擇并非總是公開的,但在公共領域對于替代方法有許多其它的建議,你的解決這個問題花的時間可能是不同的,這取決于確定的版本和容器集合的特性。