随笔:有人曾这样评价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。