Spring 3.1 发布 GA 版本了

  • Charles Humble
  • 王丽娟

2012 年 1 月 15 日

话题:Java语言 & 开发

SpringSource 在上个月中旬发布了 Spring 3.1 的 GA 版本。通过InfoQ 先前的一篇文章,我们了解了 Spring 3.1 主要的新功能,其中包括对 Java 7 的支持,还有环境抽象和缓存抽象。

Chris Beams 是 Spring 框架的主要提交者,InfoQ 就 Spring 3.1 发布的更多细节和 Spring 3.2 的计划对他进行了采访。

InfoQ:Spring 3.1 原计划是在 2011 年 6 月底发布 GA 版本。为什么会推迟到现在呢?

我们原计划要为 Spring 容器提供完全基于 Java 的配置,但这种方法在试行一段时间之后,甚至能作为完整里程碑的时候,我们对这种方法进行了反思;这种方法并不能完全满足我们的设计目标。一次完整的设计迭代之后,我们把目前的方法做成了 @Enable* 注解。

我们很早就开始支持 Servlet 3.0 容器,也遇到了一些容器实现自身的问题。我们不得不和实现容器的团队一起做一些迭代,来确保实现是正确的。

不过真正的主要原因是我们有意地扩大了范围,好让 3.1 就包括对 Java 7 提供支持,而不是等到 3.2 再开始。这主要围绕对 fork/join 的支持和 JDBC 4.1。我们还决定,要尽可能早地支持 Hibernate 4,甚至在他们发布最终版本之前。目前我们用的是 Hibernate 4 的 RC 7 版本,实际上我们的发布版本也基于 RC 7,所以 Hibernate 4.0 的最终版本一旦可用,Spring 3.1.1 就会立即升级去支持 Hibernate 4.0 最终版。

另外值得一提的是,我们不想让时间追着跑,而是尽可能提供最好的版本。所以它是连续、完整的,也能保证对用户来说是真正有意义的。

InfoQ:Spring 对 Java 7 提供了支持,这是不是能直观反映出 Java 7 的运用会比 Java 5 和 Java 6 更为迅速?

我认为是有可能的。Open JDK 和 IBM 都已经发布了 JDK 7,这是个好迹象。我们可以预测,选择基于 OpenJDK 7 的 Tomcat 7 是自然而然的。

我们当然希望 Java 7 能被迅速采用,在一定程度上,我们也希望能助它的推广和提升一臂之力。如果 Spring 有一个版本能为人们打开一道门,或许 Java 7 的推广能变得更加容易一些。

InfoQ:Spring 3.1 还利用了 Java 7 的其他哪些功能?像try-with-resources或其他Project Coin功能使用了么?

我们一直记着这些功能,还有 Java 8 里的语言特性,但 Spring 3.1 并没有过多地利用它们。大部分新特性在针对特定 API 的时候都很方便,比如 multi-catch、try-with-resources 和 switch 语句支持 String,而不像泛型这种语言特性会直接影响 API 供应商。值得注意的是,Spring 3.2 将会关注 JMS 2,并有可能和 try-with-resources 保持一致。让我们拭目以待。

InfoQ:你刚刚提到你们引入了环境抽象的概念。能给我们一个在哪里会使用它的例子么?

环境支持实际上可以分为两类:一类是属性源抽象的概念,第二类是 Bean 定义 Profile。

就属性源来说,你要是琢磨过 Java 设计,就知道获取属性的方式有很多,比如系统环境变量、JVM 系统属性、真正的 Map 或 Property 对象,或从数据库或键值存储里获得。但从语义上来说,这些属性都有共同点。它们基本上都是改变环境的配置属性。那属性源抽象就是个简单的 SPI(服务提供者接口),其实现能为应用配置提供键值对形式的后端存储。把属性源抽象加到 Spring 环境里的具体做法是,由环境维护这些你能操作和查询的属性源的层次化结构。举例来说,Spring 的 StandardEnvironment 适用于独立应用,直接使用时可以带有表示环境变量和 JVM 系统属性的属性源。对 Web 应用来说,Spring 的 StandardWebEnvironment 会把 Servlet 的 init-params、context-params 和 JNDI 属性源混杂在一起。Environment 已经深度集成到了整个容器和 Spring 的 property-placeholder 机制里;这个概念能提供一致的抽象,这样你就可以说:“Spring,告诉我这个属性的值”,应用也不需要知道或关心这个值从哪里来。

第二部分是 Bean 定义 Profile,这通常能让你基于应用的部署环境(比如开发环境、测试环境、生产环境,或者相对于传统环境的云环境)有条件地注册 Bean 定义。所以举例来说,相对于生产环境,你可以在开发环境下使用 Spring 的 JDBC 命名空间和嵌入式数据库构建器等内容来预设一个嵌入式数据库,然后在生产环境里,应用可以从 JNDI 获取数据源。

过去一段时间里我们发现有很多这样的需求,目前这也能被很好地接受了。我们希望看到人们用各种方式把它利用起来。

InfoQ:本次发布的另一个重磅内容是 Spring Cache。Spring Cache 和 Spring Data 项目是怎么协调的?

Spring 3.1 的缓存抽象是个 SPI,主要包括需要由后端缓存提供者去实现的 Cache 和 CacheManager 接口。然后还有一些共同构成声明性编程模型的注解,比如 @Cacheable、@CachePut、@CacheEvict 等。

Spring Data 实际上是个大型项目,是一组项目的集合,旨在利用模板类等大家熟悉的 Spring 机制来访问个人数据存储。这些数据存储本来有很多就适合做缓存,借助我们已经完成的集成工作,它们都可以直接使用了,比如说,GemFire 或 Redis 都是缓存提供者,因为针对 Cache 和 CacheManager 这两个 SPI,他们都提供了现成的实现。不论后端实现是什么,开发人员只需要关注 @Cacheable、@CachePut 等注解就可以了。

InfoQ:Spring Cache 和 JCache(JSR 107)有多少重叠内容?

我觉得它们是互补的,规范已经完成了,那我们肯定会为自己的缓存管理器 SPI 提供有一个基于 JCache 的实现。你可以预想到,如果接口是 CacheManager,我们就会提供一个 JCacheCacheManager,就和我们用 Spring 内核发布一个 Ehcache 管理器一样。真正漂亮的是,目前的 SPI 和 Spring Data 是我们自己实现的。有了 JCache 之后,所有供应商都会尽可能采用它,他们差不多都会去实现 JCache 的 SPI,这会进一步提升 JCache 的嵌入能力,不论后端的提供者是什么。

在编程模型方面,注解有比较多的重叠,这在一定程度上是可预见的。因为两个东西在语义上就有很多重叠,在某些情况下也会使用同一个注解。所以 JCache 一旦完成之后,我们极有可能要对自己的注解和 JCache 的注解同时提供支持。Spring 2.5 里我们引入了自己的 @Autowired 注解,这个注解同时还要支持后来被 JSR-330 标准化的 @Inject 注解,现在的情况就跟这个非常类似。

InfoQ:你们跟踪JSR 347么?你认为它对 Spring Cache 有影响么?

我不是那个规范和领域的专家,但根据它自身的优点来看,它肯定是有意义的。现在已经有很多不同的数据网格和分布式缓存提供者了;他们往往采用不同的方式去完成相似的事情。我们需要一个所有人都认可的规范来统一语义,这个规范姗姗来迟,JSR 347 就是个很不错的选择。

鉴于 JCache JSR 还没全部完成,而 JSR-347 又是以它为基础的,所以进一步推测可能有点儿为时尚早。从 Spring 的角度看,JSR-347 可能不需要为我们提供的内容做太多事情。我们主要是为后端存储提供一致的编程模型和简单的 SPI。从 JCache 的角度来看,后端存储只不过是数据存储罢了。JCache 和 JSR-347 碰巧都是分布式的,这实际上有点儿重叠。这个情况可能和 Spring 对事务管理的支持差不多。我们已经有了注解的方式和 SPI,然后可能会出现数量不定的实现,其中之一就是 JTA,但从 Spring 用户的角度来看,这确实没什么影响;JSR-347 对 Spring Cache 是有影响,但从编程模型的角度来说并没有什么关系。

InfoQ:你提到 Spring 3.2 相关的几部分内容,比如 JMS 2.0 和 JCache。能和我们再多分享一些计划里的内容么?

好的。在规范方面,我们正在研究 JPA 2.1、Bean Validation 1.1。我们也会确保 Spring 和 JSF 2.2 能很好地协作。除此之外,还有好几个我们尚未完全确认的研究领域,但我们会继续深入研究,比如并发编程方法。对于 Spring 3.1 要集成一个 fork/join 池,我们已经提供了一些非常基本的支持,但随着 fork/join 等内容的引入,应用开发模型会发生什么样的变化呢?我觉得不仅仅是 Spring,更大范围的社区对这个问题也都还没有答案。所以最高目标是,不光要搞明白这个问题,还要提供一些指导、给出一些示例应用等。

异步编程模型也是一样。对 Java 开发人员来说,Servlet 3.0 里现在就有异步工具,它们本身运行得很好,但怎么从 Spring 等 Web 框架里集成它们还悬而未决。如果你有一个启用了异步功能的 Servlet,请求管道里的其他 Servlet 组件就需要知道异步情况,所有的过滤器等也都是一样。那些 Servlet 组件要不要达到这个目标,并重构所有内容呢?对最终开发人员来说这意味着什么?对框架来说又如何呢?其他框架和我们所作的有哪些不同呢?

我们也想继续关注应用开发在云里会有怎样的变化。目前我们所了解的是一些 PaaS 提供者,它们都能正确处理那些并发访问他们平台的基于 Java 的负载;所以应用开发主要是基于 war 的部署模式和基于 Servlet 的应用。但有一个问题确实值得我们思考一下,就是“用云的特性来处理这些内容是否就是最好的方式呢?”

Chris 也谈到,他们正在重新考虑 Spring 的错误报告机制,以便配置错误相关的堆栈跟踪信息能少一些,让它能和 javac 的输出更相似;还要找一个更为现代和易于使用的工具来替换掉CGLib代理。Spring 框架的版本控制工具也会把 Subversion 换成 Git(Hub),从 3.2 开始,构建系统也会从 Ant/Ivy 换成 Gradle。

Spring 3.2 的时间表相当乐观,计划会在 2012 年的第四季度发布,大体上会遵循上面提到的那些规范。

查看英文原文Spring 3.1 is GA Today - Adds Java 7 Support, Environment Abstraction and Cache Abstraction

Java语言 & 开发