目录

spring5.0新特性

Spring5 是一个重要的版本,距离SpringFramework4差不多四年。在此期间,大多数增强都是在 SpringBoot 项目中完成的。本文会概览一些Spring5发行版中的新特性并例举几个新功能的使用。

新特性

基准升级

要构建和运行 Spring5 应用程序,你至少需要 J2EE7 和 JDK8。以前的 JDK 和 JavaEE 版本不再支持。 JavaEE7 包含:

  • Servlet 3.1
  • JMS 2.0
  • JPA 2.1
  • JAX-RS 2.0
  • Bean Validation 1.1

与 Java 基准类似,许多其他框架的基准也有变化。例如:

  • Hibernate 5
  • Jackson 2.6
  • EhCache 2.10
  • JUnit 5
  • Tiles 3

另外,请记下各种服务器最低支持版本。

  • Tomcat 8.5+
  • Jetty 9.4+
  • WildFly 10+
  • Netty 4.1+
  • Undertow 1.4+

兼容JDK9运行时

Spring5 发行版与 JDK9 发行日期非常接近。目标是让 Spring Framework5 在 JDK9 的 GA 之后正确运行。 Spring5 版本的候选版本已经在 classpath 和 modulepath 上支持 Java9 了。

GA版本中你可以期待良好的 JDK9 支持。

使用JDK8特性

在 Spring4.3 之前,JDK基准版本是6。所以 Spring4 必须支持 Java6,7 和8,为了保持向后兼容性, Spring 框架没有适应 Java8 带来的许多新特性,比如 lambda 表达式。

Spring5 的基准版本为8,因此它使用了 Java8 和9的许多新特性。例如:

  • Spring 接口中的默认方法
  • 基于 Java8 反射增强的内部代码改进
  • 在框架代码中使用函数式编程 - lambda表达式 和 stream流

响应式编程

响应式编程是 SpringFramework5.0 最重要的特性之一。响应式编程提供了另一种编程风格,专注于构建对事件做出响应的应用程序。 SpringFramework5 包含响应流(定义响应性API的语言中立尝试)和 Reactor(由Spring Pivotal团队提供的 Reactive Stream 的Java实现), 以用于其自身的用途以及其许多核心API。

Spring Web Reactive 在 spring-webmvc 模块中现有的(而且很流行)Spring Web MVC旁边的新的 spring-web-reactive 模块中。 请注意,在 Spring5 中,传统的 SpringMVC 支持 Servlet3.1 上运行,或者支持 JavaEE7 的服务器。

函数式编程

除了响应式功能之外,Spring5 还提供了一个函数式Web框架。它提供了使用函数式编程风格来定义端点的特性。 该框架引入了两个基本组件:HandlerFunction 和 RouterFunction。

HandlerFunction 表示处理接收到的请求并生成响应的函数。 RouterFunction 替代了 @RequestMapping 注解。它用于将接收到的请求路由到处理函数。例如:

1
2
3
4
5
RouterFunction<String> route =

route(GET("/hello-world"),

request -> Response.ok().body(fromObject("Hello World")));

Kotlin支持

Kotlin 是一种静态类型的JVM语言,它让代码具有表现力,简洁性和可读性。 Spring5.0 对 Kotlin 有很好的支持。

移除的特性

随着 Java、JavaEE 和其他一些框架基准版本的增加,SpringFramework5 取消了对几个框架的支持。例如:

  • Portlet
  • Velocity
  • JasperReports
  • XMLBeans
  • JDO
  • Guava

部分新功能的使用

支持整合log4j2

spring5已经移除了Log4jConfigListener,如果要使用log4j的话只能降版本了,官方建议使用log4j2

使用log4j2很简单,直接引用其相关jar包,spring在运行过程中会自动检测并使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
</dependency>

支持@Nullable注解

@Nullable 注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空。

Spring5 核心容器支持函数式风格 GenericApplicationContext

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.eh.eden.spring.demo;

import org.springframework.context.support.GenericApplicationContext;

public class Demo {

    //函数式风格创建对象,交给 spring 进行管理
    public static void main(String[] args) {
        //1 创建 GenericApplicationContext 对象
        GenericApplicationContext context = new GenericApplicationContext();

        //2 调用 context 的方法对象注册
        context.refresh();
        context.registerBean("helloWorld", HelloWorld.class, () -> new HelloWorld());

        //3 获取在 spring 注册的对象
//        HelloWorld helloWorld = (HelloWorld) context.getBean("com.eh.eden.spring.demo.HelloWorld");

        HelloWorld helloWorld = context.getBean("helloWorld", HelloWorld.class);
        helloWorld.sayHello();
    }
}

支持整合Junit5

引入junit5和spring-test jar包

1
2
3
4
5
6
7
8
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
</dependency>

编写测试单元

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package com.eh.eden.spring.demo;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;


@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:beans.xml")
public class HelloWorldTest {

    @Autowired
    private HelloWorld helloWorld;

    @Test
    public void testSay() {
        helloWorld.sayHello();
    }
}

也可以使用复合注解替代上面两个注解完成整合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package com.eh.eden.spring.demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;


@SpringJUnitConfig(locations = "classpath:beans.xml")
public class HelloWorldTest {

    @Autowired
    private HelloWorld helloWorld;

    @Test
    public void testSay() {
        helloWorld.sayHello();
    }
}