翻译:Spring框架参考文档第一部分

官方文档地址:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#spring-introduction

作者列表

Rod Johnson , Juergen Hoeller , Keith Donald , Colin Sampaleanu , Rob Harrop , Thomas Risberg , Alef Arendsen , Darren Davison , Dmitriy Kopylenko , Mark Pollack , Thierry Templier , Erwin Vervaet , Portia Tung , Ben Hale , Adrian Colyer , John Lewis , Costin Leau , Mark Fisher , Sam Brannen , Ramnivas Laddad , Arjen Poutsma , Chris Beams , Tareq Abedrabbo , Andy Clement , Dave Syer , Oliver Gierke , Rossen Stoyanchev , Phillip Webb , Rob Winch , Brian Clozel , Stephane Nicoll , Sebastien Deleuze

4.3.8.RELEASE

版权所有© 2004-2016
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
只要您不对这些副本收取任何费用,并且进一步规定,每个副本都包含本版权声明,无论是以印刷版还是电子版分发,本文档的副本可供您自己使用并分发给他人。

第一部分 Spring框架概述

Spring Framework是一个轻量级解决方案,可以一站式的构建企业级应用程序。但是,Spring是模块化的,允许使用部分所需的部件,而不使用其余的部件。可以在任何Web框架上使用控制反转(IoC),也可以仅仅是用 Hibernate集成代码或者JDBC抽象层。Spring框架支持声明式事务管理,通过RMI或Web服务远程访问您的逻辑,以及用于持久存储数据的各种选项。它提供了一个全功能的MVC框架,使您能够将AOP透明地集成到您的软件中。

Spring被设计为非侵入性的,这意味着您的域逻辑代码通常不依赖于框架本身。在集成层(如数据访问层)中,会存在一些依赖同时依赖于数据访问技术和Spring,但是这些依赖可以很容易地从代码库中分离出来。
本文档是Spring Framework功能的参考指南。如果您对本文档有任何要求,意见或问题,请将其发布在 用户邮件列表中。或者在StackOverflow上询问框架本身的问题(请参阅https://spring.io/questions)。

1. Spring入门

本参考指南提供有关Spring框架的详细信息。它为所有功能提供了全面的文档,以及Spring所提供的基本概念(如“依赖注入”)的背景知识。

如果您刚开始使用Spring,可以通过创建一个 Spring Boot的基本应用程序来开始使用Spring框架。Spring Boot提供了一种快速(有选择的)的方式创建一个基于生产的Spring应用程序。它基于Spring框架,有利于配置的设定,从而使得程序尽快开始运行。

您可以使用start.spring.io生成一个基本项目,或按照“入门指南”中的一个指南,例如开始创建RESTful 项目入门 。除了易于理解以外,这些指南非常任务化,大部分都是基于Spring Boot。他们还涵盖了Spring解决方案中您可能想要考虑的其他项目。

2. Spring框架介绍

Spring 框架是一个Java平台,为开发Java应用程序提供全面的基础设施支持。Spring很好的处理了基础设施,因此可以专注于应用程序开发。
Spring使您能够从“简单的Java对象”(POJO)构建应用程序,并将企业服务非侵入式应用于POJO。此功能适用于Java SE编程模型以及完整和部分的Java EE。
那么作为应用程序开发人员,我们可以从Spring平台中得到什么呢:

  • 使Java方法在数据库事务中执行,而不必处理事务API。
  • 使本地Java方法成为HTTP端点,而无需处理Servlet API。
  • 使本地Java方法成为消息处理程序,而无需处理JMS API。
  • 使本地Java方法成为管理操作,而无需处理JMX API。

2.1依赖注入和控制反转

一个Java应用程序,从受限制的嵌入式应用到n层的服务端应用,典型地是由相互合作的对象组成的,因此,一个应用程序中的对象是相互依赖的。
虽然Java平台提供了丰富的应用程序开发功能,但它缺乏将基本构建块组织成一个连贯的整体的方法,将该任务留给架构师和开发人员。可以使用工厂模式Factory,抽象工厂模式Abstract Factory,创建者模式Builder,装饰者模式Decorator和服务定位器模式Service Locator等设计模式来构成构成应用程序的各种类和对象实例,这些模式是简单的:因为框架给出这些设计模式名称对应的最佳实践,以及什么样的模式,应用于哪里,它解决的问题等等。这些设计模式都是最佳实践的结晶,所以你应该在你的应用程序中使用它们。
Spring的控制反转解决了上述问题,它提供了一种正式的解决方案,你可以把不相干组件组合在一起,从而组成一个完整的可以使用的应用。Spring根据设计模式编码出了非常优秀的代码,所以可以直接集成到自己的应用中。因此,大量的组织机构都使用Spring来保证应用程序的健壮性和可维护性。

**背景** 
Martin Fowler 在2004年在他的网站上提出了关于控制反转(IoC)的问题“The question is, what aspect of control are [they] inverting?”。
Fowler 由此建议重新命名这个原则,使其更加清晰明了,并提出依赖注入。

2.2框架模块

Spring框架由组织成约20个模块的功能组成。这些模块分为核心容器Core Container,数据访问/集成Data Access / IntegrationWebAOP(面向对象编程),Instrumentation,消息处理Messaging和测试Test,如下图所示。

图2.1 Spring框架概述

以下部分列出了每个功能对应的模块及主题,并且提供功能的Artifact nameArtifact name与依赖关系管理工具中使用的Artifact name相关联。

2.2.1核心集装箱Core Container

核心容器spring-corespring-beansspring-contextspring-context-support,和spring-expression(Spring表达式语言)多个模块组成。

spring-corespring-beans模块是Spring框架的基础,包括IoC控制反转和依赖注入。而BeanFactory是工厂模式的复杂实现。它消除了对编程单例的需要,并允许将依赖关系的配置和规范与实际程序逻辑分离。

Spring上下文模块spring-context建立在Spring核心CoreBean模块之上:它以一个JNDI注册的方式去访问一个对象。上下文模块Context继承自Beans模块,并增加了对国际化的支持(例如使用资源束),事件传播,资源加载以及透明创建上下文对象,例如Servlet容器。Context模块还支持Java EE功能,如EJB,JMX(Java Management Extensions,即Java管理扩展)和基本远程处理。ApplicationContext接口是上下文模块的关键点。spring-context-support支持将常见的第三方库集成到Spring应用程序上下文缓存(EhCache,Guava,JCache),邮件(JavaMail),调度(CommonJ,Quartz)和模版引擎(FreeMarker,JasperReports,Velocity)中

spring-expression模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是JSP 2.1规范中规定的统一表达语言(统一EL)的扩展。该语言支持设置和获取属性值,属性分配,方法调用,访问数组,集合和索引器的内容,逻辑和算术运算符,命名变量以及从Spring的IoC容器中以名称检索对象。它还支持列表投影和选择以及常见列表聚合。

2.2.2 AOP和检测Instrumentation

spring-aop模块提供了一个符合AOP联盟标准的面向对象的编程实现,允许您定义方法拦截器和切入点,用于分离实现可分离的功能代码。使用源级别元数据功能,您还可以以类似于.NET属性的方式将行为信息合并到代码中。

独立的spring-aspects模块提供与AspectJ(一个面向切面的框架)的集成。

spring-instrument模块提供了对检测类的支持和用于特定的应用服务器的类加载器的实现。spring-instrument-tomcat模块包含用与Tomcat的Spring测试代理。

2.2.3消息传递

Spring 4包含的spring-messaging是从Spring集成项目中抽象出来的模块,例如MessageMessageChannelMessageHandler,和其他基于消息的基础应用程序。该模块还包括一组用于将消息映射到方法的注释,类似于基于Spring MVC注释的编程模型。

2.2.4数据访问/集成

数据访问/集成层由JDBC,ORM,OXM,JMS和事务模块组成。

spring-jdbc模块提供了一个JDBC抽象层,可以省去冗长的JDBC编码和解析数据库供应商特定错误代码的需要。

spring-tx模块支持编程式事务和声明式事务,可用于实现了特定接口的类和所有的POJO对象。
(译者注:编程式事务需要自己写beginTransaction()、commit()、rollback()等事务管理方法,声明式事务是通过注解或配置由spring自动处理,编程式事务粒度更细)

spring-orm模块为流行的对象关系映射API提供集成层 ,包括JPA, JDO和Hibernate。使用spring-orm模块,您可以将所有这些O/RMapping框架与Spring提供的所有其他功能结合使用,例如前面提到的简单的声明式事务管理功能。

spring-oxm模块提供了一个支持Object/XML映射实现(如JAXB,Castor,XMLBeans,JiBX和XStream)的抽象层。

spring-jms模块(Java消息服务)包含用于生成和消费消息的功能。自Spring Framework 4.1以来,它提供了与spring-messaging模块的集成。

2.2.5 网络Web

网络层由spring-webspring-webmvcspring-websocket,和 spring-webmvc-portlet模块组成。

spring-web模块提供基本的面向Web的集成功能,例如多部分multipart文件上传功能,使用Servlet监听器初始化IoC容器等。它还包含一个HTTP客户端和Spring的远程支持的Web相关部分。

spring-webmvc模块(也称为Web-Servlet模块)包含用于Web应用程序的Spring的模型视图控制器model-view-controller(MVC)和REST Web Services实现。Spring MVC架构提供了领域模型代码和Web表单之间的分离,并与Spring框架的其他所有功能集成。

spring-webmvc-portlet模块(也称为Web-Portlet模块)提供了在Portlet环境中使用的MVC实现,并反映了基于Servlet的spring-webmvc模块的功能。

2.2.6测试

spring-test模块支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。它提供一致性加载和Spring应用程序上下文ApplicationContext,以及缓存这些上下文。它还提供可用于独立测试代码的模拟对象的功能。

2.3使用场景

之前描述的构建块使Spring成为许多场景中的逻辑选择,不管是在资源受限设备上运行的嵌入式应用程序,或者使用Spring的事务管理功能和Web框架集成的企业级应用程序。

图2.2 典型的成熟的Spring Web应用程序

Spring的声明式事务管理功能使Web应用程序完全事务性,就像使用EJB容器管理的事务一样。所有您的定制业务逻辑都可以使用简单的POJO实现,并由Spring的IoC容器进行管理。附加服务包括支持发送电子邮件和独立于Web层的验证,可让您选择执行验证规则的位置。Spring的ORM支持与JPA,Hibernate和JDO集成; 例如,当使用Hibernate时,您可以继续使用现有的映射文件和标准的Hibernate SessionFactory配置。表单控制器将Web层与域模型无缝集成,移除了将ActionFormsHTTP参数转换为域模型的值或其他类的需求。

图2.3 Spring中间层使用第三方网络框架

有时情况不允许你完全切换到不同的框架。Spring框架不会强制使用其内的所有模块; 这不是一个要么全有,要么全没有的解决方案。使用StrutsTapestryJSF或其他UI框架构建的现有前端可以与基于Spring的中间层集成,从而允许您使用Spring事务功能。您只需使用一个应用程序上下文对象ApplicationContext连接您的业务逻辑,并使用WebApplicationContext来集成Web层。

图2.4 远程使用场景

当你需要通过Web服务来访问现有的代码,你可以使用Spring框架的的Hessian-Burlap-Rmi-JaxRpcProxyFactory类。启用对现有应用程序的远程访问并不困难。

图2.5 EJBs - 包装现有的POJO

Spring框架还为Enterprise JavaBeans提供了一个访问抽象层,使您能够重用现有的POJO,并将其包装在无状态会话bean中,以用于可能需要声明式安全性的可扩展的,故障安全的Web应用程序。

2.3.1依赖管理和命名约定

依赖关系管理和依赖注入是不同的。为了将Spring的这些不错的功能引入到应用程序中(如依赖注入),您需要组装所有需要的库(jar文件),并在运行时和编译时将它们导入到类路径中。这些依赖关系不是注入的虚拟组件,而是文件系统中的物理资源(通常情况下如此)。依赖关系管理的过程包括定位这些资源,存储它们并将其添加到类路径中。依赖关系可以是直接的(例如,我的应用程序在运行时依赖Spring)或间接(例如我的应用程序取决于commons-dbcp哪个依赖于commons-pool)。间接依赖关系也被称为“传递性”,它们是最难识别和管理的依赖关系。

如果你要使用Spring框架,你需要获得一个包含你所需要的Spring块的jar库的副本。为了使获取更容易,Spring框架被打包为一组尽可能分离依赖关系的模块,例如,如果您不想编写Web应用程序,则不需要spring-web模块。本指南中,我们使用速记命名约定到Spring库模块spring-*spring-*.jar,其中*代表该模块的短名称(例如spring-corespring-webmvcspring-jms等)。您使用的实际jar文件名通常是用模块名称与版本号连接(例如spring-core-4.3.8.RELEASE.jar)。

Spring框架的每个版本都会将包Artifact发布到以下位置:

  • Maven CentralMaven中央仓库
    它是Maven查询的默认存储库,不需要任何特殊配置。Spring的许多常见的库也可以从Maven Central获得,Spring框架的大部分功能使用Maven进行依赖关系管理,所以这是很方便的。jar包的名称是spring-*-<version>.jar,Maven库中groupId是org.springframework
  • 在专门用于放置Spring框架的公共Maven存储库中。除了最终的GA版本,该存储库还有开发版snapshots和里程碑版本milestones。jar包命名格式与Maven Central的格式相同,这样放置也是很有用的,可以将Spring的开发版本snapshots与在Maven Central中部署的其他库一起使用。该存储库还包含压缩后的zip文件,其中包含所有Spring框架用到的jar包,压缩在一起以便于下载。

因此您需要确定的第一件事是如何管理您的依赖关系:我们通常建议使用像MavenGradleIvy这样的自动化系统,但您也可以通过自己下载所有的jar包来手动进行操作。

下面你将会看到Spring工件的列表。有关每个模块的更完整的描述,请参见第2.2节“框架模块”。

表2.1. Spring框架工件

GroupId ArtifactId Description
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为大量企业和其他外部工具提供集成和支持,但它有意将其强制性依赖性保持在最低限度:您不必因为想要使用Spring框架搭建简单的用例,而去定位和下载(甚至自动)大量的jar库。对于基本依赖注入,只有一个强制性的外部依赖关系,也就是用于日志记录(有关日志记录选项的更详细描述,请参见下文)。

接下来,我们概述了配置依赖于Spring的应用程序所需的基本步骤,首先是使用Maven,然后使用Gradle,最后使用Ivy。在任何情况下,如果不清楚,请参阅依赖关系管理系统的文档,或查看一些示例代码 - Spring本身在构建时使用Gradle来管理依赖关系,而且我们的示例主要使用Gradle或Maven。

Maven依赖管理

如果您使用Maven进行依赖关系管理,则甚至不需要显式提供记录依赖关系。例如,要创建应用程序上下文并使用依赖注入来配置应用程序,您的Maven依赖项将如下所示:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.8.RELEASE</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

就这样,注意如果不需要编译Spring API,可以把scope声明为runtime,这是依赖注入使用的典型案例。

上面的示例使用Maven中央仓库,如果使用Spring的Maven仓库(例如,里程碑版本milestones或开发快照版本snapshots),需要在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“物料清单式”依赖

使用Maven时,可能会意外混合不同版本的Spring JAR包。例如,您可能从第三方库中下载,或另一个Spring项目存在旧的版本依赖。如果您忘记自己明确声明直接依赖,可能会出现各种意外问题。

为了克服这些问题,Maven支持“物料单”(BOM)依赖的概念。您可以导入spring-framework-bom到您的dependencyManagement部分,以确保所有Spring依赖(直接和传递)都是相同的版本。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>4.3.8.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

使用BOM的一个额外的好处是,您不再需要在引用Spring框架工件时去指定<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构建系统中使用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.8.RELEASE")
    testCompile("org.springframework:spring-test:4.3.8.RELEASE")
}
Ivy依赖关系管理

使用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中):

发行版的Zip文件

虽然使用支持依赖管理的构建系统是获取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。发行文件也包含里程碑版本和快照版本。

2.3.2 日志记录

日志记录是Spring非常重要的功能依赖,因为a) 它是唯一的强制性外部依赖关系,b) 每个人都喜欢看到他们使用的工具的一些输出,c) Spring集成了许多其他工具,它们都选择了日志依赖关系。

应用程序开发人员的目标之一通常是将统一的日志记录配置在整个应用程序的中央位置,包括所有外部组件。这比以前更加困难,因为日志框架有太多选择。

Spring中的强制性日志依赖关系是Jakarta Commons Logging API(JCL)。我们针对JCL进行编译,我们也使JCL Log对象对于扩展Spring Framework的类可见。对于用户来说,所有版本的Spring都使用相同的日志库,这样做非常重要,这样做以后迁移很简单,因为即使扩展Spring的应用程序仍然保留向后兼容性。我们这样做的方法是使Spring中的一个模块明确地依赖于commons-logging(JCL的规范实现),然后在编译时使所有其他模块依赖于它。例如,如果您使用Maven,并且想知道您在哪里选择对commons-logging的依赖关系,那么它来自Spring,特别是来自中央模块spring-core

使用commons-logging更为方便的是,你不需要任何其他东西来使你的应用程序工作。它具有运行时发现算法,可以在配置的类路径中查找其他日志记录框架,并使用它认为合适的记录框架(或者您可以告诉它需要哪一个)。如果没有其他可用的,您可以从JDK(简称java.util.logging或JUL)获得非常实用的日志。由此你可以发现,在大多数情况下,你的Spring程序都可以正常的工作,并且能够输出信息到控制台,这是很重要的。

使用Log4j 1.2或者2.x

Log4j 1.2在此期间是EOL。此外,Log4j 2.3是最新的Java 6兼容版本,较新的Log4j 2.x版本需要Java 7+版本。
许多人使用Log4j作为配置和管理目的的日志框架。它高效且成熟,实际上在我们在构建Spring时,它是在运行时使用的。Spring还提供了一些用于配置和初始化Log4j的实用程序,因此它在某些模块中对Log4j具有可选的编译时依赖性。

要使Log4j 1.2使用默认的JCL依赖项(commons-logging),您需要做的就是将Log4j放在类路径上,并为其提供配置文件(log4j.propertieslog4j.xml在类路径的根目录中)。所以对于Maven用户来说,这是你的依赖声明:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.8.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</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

要使用Log4j 2.X与JCL,你需要做的就是把Log4j放到在类路径下,并为其提供一个配置文件(log4j2.xmllog4j2.properties或其他支持的配置格式)。对于Maven用户,所需的最小依赖关系是:

<dependencies>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.6.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-jcl</artifactId>
        <version>2.6.2</version>
    </dependency>
</dependencies>

如果您还希望启用SLF4J委托Log4j,例如默认使用SLF4J的其他库,则还需要以下依赖关系:

<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.6.2</version>
  </dependency>
</dependencies>

以下是使出日志到控制台的示例配置文件log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="org.springframework.beans.factory" level="DEBUG"/>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>
避免使用Commons Logging

不幸的是,标准commons-loggingAPI中的运行时发现算法对于最终用户来说方便,但是可能是有问题的。如果你想避免JCL的标准查找,基本上有两种方法来关闭它:

  1. spring-core模块中排除依赖关系(因为它是唯一明确依赖的模块commons-logging
  • 取决于一个特殊的commons-logging依赖关系,用空的jar代替库(更多的细节可以在SLF4J FAQ中找到 )

要排除公共记录,请将以下内容添加到您的dependencyManagement部分:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.8.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

现在这个应用程序目前被破坏,因为在类路径中没有实现JCL API,所以要修复它,必须提供一个新的JCL API。在下一节中,我们向您展示如何使用SLF4J提供JCL的替代实现。

使用SLF4J与Log4j或Logback

Java简单日志模式(SLF4J)是Spring常用的其他库流行API。它通常配合SLF4J API本地化的Logback使用。

SLF4J提供了绑定到许多常见的日志记录框架的功能,包括Log4j,并且它也可以完成相反的工作:其他日志记录框架和其自身之间的桥梁。所以要使用SLF4J与Spring,您需要使用SLF4J-JCL桥替代commons-logging的依赖关系配置。一旦完成,那么在Spring中记录调用将被转换为对SLF4J API的记录调用,因此如果应用程序中的其他库使用该API,那么就会有一个单独的地方来配置和管理日志记录。

常见的选择可能是将Spring链接到SLF4J,然后提供从SLF4J到Log4j的显式绑定。您需要提供几个依赖关系(并排除现有的commons-logging):JCL桥接器,SLF4j绑定到Log4j,以及Log4j提供器。在Maven中,你可以这样做

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.8.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.7.21</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.21</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

SLF4J用户更为常见的选择,是使用较少的步骤以及生成更少的依赖关系,就是直接绑定到Logback。因为直接的logback实现SLF4J,也会消除多余的绑定步骤,所以你只需要仅仅依靠两个库,即jcl-over-slf4jlogback):

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.7.21</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.1.7</version>
    </dependency>
</dependencies>
使用JUL(java.util.logging

只要在类路径中没有检测到Log4j,Commons Logging都会默认委派java.util.logging。所以没有什么特别的依赖关系:在一个独立的应用程序(在JDK级别使用自定义或默认的JUL设置)中只要在使用Spring是没有配置外部依赖,日志输出就会使用java.util.logging,或应用程序服务器的日志系统(和它的系统级JUL设置)。

Commons登录WebSphere

Spring应用程序可以在本身提供JCL实现的容器上运行,例如IBM的WebSphere Application Server(WAS)。这并不会导致问题本身,而是导致需要了解的两种不同的场景:

在“父级第一”ClassLoader授权模型(WAS中的默认值)中,应用程序将始终选择Commons Logging提供的服务器版本,委托给WAS记录子系统(实际上基于JUL)。JCL的应用程序提供的变量,无论是标准的Commons Logging还是JCL-over-SLF4J桥,都将被有效地被忽略,以及任何本地包含的日志提供程序。

使用“父进程”委托模式(常规Servlet容器中的默认值,WAS上的显式配置选项),在您的应用程序中,将提取应用程序提供的Commons Logging变量,使您能够设置本地包含的日志提供程序,例如Log4j或Logback。在没有本地日志提供程序的情况下,默认情况下,常规Commons Logging将委托给JUL,有效地记录到WebSphere的日志记录子系统,同“父级第一”方案一致。

总而言之,我们建议将“Spring”应用程序部署在“父进程”模式中,因为它自然地允许本地提供程序以及服务器的日志子系统。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容