我这样回答了Spring 5的新特性,面试官对我另眼相看

最近,有一个小伙伴拿到了本身满意的Offer,和他交谈的过程当中得知他面试官问他关于Spring的问题比较多,其中最让面试官满意的就是本身回答关于Spring 5的知识点回答的不错。java

Spring5于2017年9月发布了通用版本,它是自2013年12月以来第一个主要的Spring版本。它提供了一些人们期待已久的改进,还采用了一种全新的编程范例,以反应式原则为基础。程序员

这个版本是很长时间以来最使人激动的版本。Spring 5兼容Java™8和JDK 9,它集成了反应式流,以方便后续提供一种颠覆性方法来实现端点和Web应用程序开发。web

固然,反应式编程不只是此版本的主题,仍是令许多程序员激动不已的重大特性。人们对可以针对负载波动进行无缝扩展的容灾和响应式服务的需求在不断增长,Spring 5很好地知足了这一需求。面试

下面介绍Java SE 8和Java EE 7 API升级的基本内容、Spring 5的新反应式编程模型、对HTTP/2的支持,以及Spring经过Kotlin对函数式编程的全面支持。还会简要介绍测试和性能加强,最后介绍对Spring核心和容器的通常性修订。spring

升级到Java SE 8和Java EE 7编程

之前的Spring一直在支持一些弃用的Java版本,而Spring 5已从“旧包袱”中解放出来。为了充分利用Java 8的特性,它的代码库已进行了改进,并且要求将Java 8做为最低的JDK版本。api

Spring 5在类路径(和模块路径)上彻底兼容Java 9,并且它经过了JDK 9测试套件的测试。对Java 9爱好者而言,这是一个好消息。服务器

在API级别上,Spring 5兼容Java EE 8技术,知足对Servlet 4.0、Bean Validation 2.0和全新的JSON Binding API的需求。对Java EE API的最低要求为V7,该版本引入了针对Servlet、JPA和Bean Validation API的次要版本。架构

反应式编程模型并发

Spring 5最使人兴奋的新特性是它的反应式编程模型。Spring 5基于一种反应式基础而构建,并且是彻底异步和非阻塞的。只需少许的线程,新的事件循环执行模型就能够垂直扩展。

Spring 5采用反应式流来提供在反应式组件中传播负压的机制。负压是一个确保来自多个生产者的数据不会让使用者不堪重负的概念。

Spring WebFlux是Spring 5的反应式核心,它为开发人员提供了两种为Spring Web编程而设计的编程模型:基于注解的模型和Functional WebFramework(WebFlux.fn)。

基于注解的模型是Spring Web MVC的现代替代方案,该模型基于反应式基础而构建,而Functional Web Framework是基于@Controller注解的编程模型的替代方案。这些模型都经过同一种反应式规则来运行,后者调整非阻塞HTTP来适应反应式流API。

使用注解进行编程

Web MVC程序员应该对Spring 5的基于注解的编程模型很是熟悉,Spring 5调整了Web MVC的@Controller编程模型,采用了相同的注解。

在下面的代码中BookController类提供了两个方法,分别响应针对某个图书列表的HTTP请求,以及针对具备给定id的图书的HTTP请求。请注意Mono和Flux等对象。这些对象是实现反应式流规范中的Publisher接口的反应式类型,它们的职责是处理数据流。Mono对象处理一个仅含1个元素的流,而Flux表示一个包含N个元素的流。

@RestController
public class BookController { //反应式控制器
@GetMapping("/book")
Flux<Book> list() {
returnthis.repository.findAll();
}
@GetMapping("/book/{id}")
Mono<Book> findById(@PathVariable String id) {
returnthis.repository.findOne(id);
}
}

以上是针对Spring Web编程的注解,下面咱们使用函数式Web框架来解决同一个问题。

函数式编程

Spring 5的函数式方法将请求委托给处理函数,这些函数接收一个服务器请求实例并返回一种反应式类型。来看一段代码,建立BookHandler类,其中listBooks()和getBook()方法至关于Controller中的功能。

publicclassBookHandler {
public Mono<ServerResponse> listBooks(ServerRequest request) {
return ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(repository.allPeople(), Book.class);
}
public Mono<ServerResponse> getBook(ServerRequest request) {
return repository.getBook(request.pathVariable("id"))
.then(book -> ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(fromObject(book)))
.otherwiseIfEmpty(ServerResponse.notFound().build());
}
}

经过路由函数来匹配HTTP请求参数与媒体类型,将客户端请求路由处处理函数。下面的代码展现了图书资源端点URI将调用委托给合适的处理函数:

BookHandler handler = new BookHandler();
RouterFunction<ServerResponse> personRoute =
route(
GET("/books/{id}")
.and(accept(APPLICATION_JSON)), handler::getBook)
.andRoute(
GET("/books")
.and(accept(APPLICATION_JSON)), handler::listBooks);

这些示例背后的数据存储也支持完整的反应式体验,该体验是经过Spring Data对反应式 Couchbase、Reactive MongoDB和Cassandra的支持来实现的。

使用 REST 端点执行反应式编程

新的编程模型脱离了传统的Spring Web MVC模型,引入了一些很不错的新特性。

举例来讲,WebFlux模块为RestTemplate提供了一种彻底非阻塞、反应式的替代方案,名为WebClient。下面建立一个WebClient,并调用books端点来请求一本给定id为1234的图书。

//经过WebClient调用REST端点
Mono<Book> book =WebClient.create("http://localhost:8080")
.get()
.url("/books/{id}", 1234)
.accept(APPLICATION_JSON)
.exchange(request)
.then(response -> response.bodyToMono(Book.class));

支持HTTP/2

HTTP/2提升了传输性能,减小了延迟,并提升了应用程序的吞吐量,从而提供了丰富的Web体验。

Spring 5提供专门的HTTP/2特性支持,还支持人们指望出如今JDK 9中的新HTTP客户端。尽管HTTP/2的服务器推送功能已经过Jetty Servlet引擎的ServerPushFilter类向Spring开发人员公开很长一段时间了,但若是发现Spring 5中开箱即用地提供了HTTP/2性能加强,Web优化者们必定会为此欢呼雀跃。

Spring 5.1提供Servlet 4.0,HTTP/2新特性将由Tomcat 9.0、Jetty9.3和Undertow 1.4原生提供。

Kotlin和Spring WebFlux

Kotlin是一种来自JetBrains的面向对象语言,支持函数式编程。它的主要优点之一是与Java有很是高的互操做性。经过引入对Kotlin的专门支持,Spring 5全面吸纳了这一优点。它的函数式编程风格与Spring WebFlux模块完美匹配,它的新路由DSL利用了函数式Web框架及干净且符合语言习惯的代码。能够像下面代码中这样简单地表达端点路由:

//Kotlin用于定义端点的路由DSL
@Bean
fun apiRouter() = router {
(accept(APPLICATION_JSON) and "/api").nest {
"/book".nest {
GET("/", bookHandler::findAll)
GET("/{id}", bookHandler::findOne)
}
"/video".nest {
GET("/", videoHandler::findAll)
GET("/{genre}", videoHandler::findByGenre)
}
}
}

使用Kotlin 1.1.4以上版本时,还添加了对Kotlin的不可变类的支持(经过带默认值的可选参数),以及对彻底支持null的API的支持。

使用Lambda表达式注册Bean

做为传统XML和JavaConfig的替代方案,如今可使用Lambda表达式注册Spring Bean,使Bean能够实际注册为提供者。下面代码中使用Lambda表达式注册了一个Book Bean:

GenericApplicationContext context = newGenericApplicationContext();
context.registerBean(Book.class, () ->new
Book(context.getBean(Author.class))
);

Spring Web MVC支持最新的 API

全新的WebFlux模块提供了许多新的、使人兴奋的功能,但Spring 5也迎合了愿意继续使用 Spring MVC的开发人员的需求。Spring 5中更新了“模型-视图-控制器”框架,以兼容WebFlux和最新版的Jackson 2.9和Protobuf 3.0,甚至包括对新的Java EE 8 JSON-Binding API的支持。

除了HTTP/2特性的基础服务器实现,Spring Web MVC还经过MVC控制器方法的一个参数来支持Servlet 4.0 的PushBuilder。最后,Web MVC全面支持Reactor 3.1的Flux和Mono对象,以及RxJava 1.3和RxJava 2.1,它们被视为来自MVC控制器方法的返回值。这项支持的最终目的是支持Spring Data中新的反应式WebClient和反应式存储库。

使用JUnit 5执行条件和并发测试

1. JUnit和Spring 5

Spring5全面接纳了函数式范例,并支持JUnit5及其新的函数式测试风格。还提供了对JUnit 4的向后兼容性,以确保不会破坏旧代码。

Spring5的测试套件经过多种方式获得了加强,但最明显的是它对JUnit 5的支持。如今能够在单元测试中利用Java 8中提供的函数式编程特性。如下代码演示了这一支持:

@Test
void givenStreamOfInts_SumShouldBeMoreThanFive() {
assertTrue(Stream.of(20, 40, 50)
.stream()
.mapToInt(i -> i)
.sum() > 110, () -> "Total should be more than 100");
}

2. 迁移到JUnit 5

若是你对升级到JUnit 5持观望态度,StevePerry的分两部分的深刻剖析教程将说服你进行尝试。

Spring5继承了JUnit 5在Spring TestContext Framework内实现多个扩展API的灵活性。举例,开发人员可使用JUnit 5的条件测试执行注解@EnabledIf和@DisabledIf来自动计算一个SpEL(Spring Expression Language)表达式,并适当地启用或禁用测试。借助这些注解,Spring 5支持之前很难实现的复杂的条件测试方案。SpringTextContext Framework如今可以并发执行测试。

3. 使用 Spring WebFlux 执行集成测试

Spring Test如今包含一个WebTestClient,后者支持对Spring WebFlux服务器端点执行集成测试。WebTestClient使用模拟请求和响应来避免耗尽服务器资源,并能直接绑定到WebFlux服务器的基础架构。

WebTestClient可绑定到真实的服务器,或者使用控制器或函数。在下面的代码中,WebTestClient被绑定到localhost:

WebTestClient testClient = WebTestClient
.bindToServer()
.baseUrl("http://localhost:8080")
.build();

下面的代码将WebTestClient绑定到RouterFunction:

RouterFunction bookRouter = RouterFunctions.route(
RequestPredicates.GET("/books"),
request -> ServerResponse.ok().build()
);
WebTestClient
.bindToRouterFunction(bookRouter)
.build().get().uri("/books")
.exchange()
.expectStatus().isOk()
.expectBody().isEmpty();

包清理和弃用

Spring5终止了对一些过期API的支持。遭此厄运的有Hibernate 3和Hibernate 4,为了支持Hibernate 5,它们遭到了弃用。另外,对Portlet、Velocity、JasperReports、XMLBeans、JDO和Guava的支持也已终止。

包级别上的清理工做仍在继续。Spring 5再也不支持beans.factory.access、jdbc.support.nativejdbc、mock.staticmock(来自spring-aspects模块)或web.view.tiles2M。Tiles 3如今是Spring的最低要求。

Spring核心和容器的通常更新

Spring 5改进了扫描和识别组件的方法,使大型项目的性能获得提高。目前,扫描是在编译时执行的,并且向META-INF/spring.components文件中的索引文件添加了组件坐标。该索引是经过一个为项目定义的特定于平台的应用程序构建任务来生成的。

标有来自javax包的注解的组件会添加到索引中,任何带@Index注解的类或接口都会添加到索引中。Spring的传统类路径扫描方式没有被删除,而是保留下来做为一种后备选择。有许多针对大型代码库的明显性能优点,托管许多Spring项目的服务器也会缩短启动时间。

Spring 5还添加了对@Nullable的支持,后者可用于指示可选的注入点。使用者如今必须准备接受null值。此外,还可使用此注解来标记能够为null的参数、字段和返回值。@Nullable主要用于IntelliJ IDEA等IDE,但也可用于Eclipse和FindBugs,它使得在编译时处理null值变得更方便,无须在运行时发送NullPointerExceptions。

Spring Logging还提高了性能,自带开箱即用的Commons Logging桥接器。如今已经过资源抽象支持防护性编程,为getFile访问提供了isFile指示器。

我如何看Spring 5

Spring 5的首要特性是新的反应式编程模型,这表明着对提供可无缝扩展、基于Spring的响应式服务的重大保障。随着人们对Spring 5的采用,反应式编程有望成为使用Java语言的Web和企业应用程序开发的将来。

将来的Spring将继续体现这一承诺,由于SpringSecurity、Spring Data和Spring Integration有望采用反应式编程的特征和优点。

总之,Spring 5表明着一次大受Spring开发人员欢迎的华丽转变,同时也为其余框架指出了一条发展之路。Spring 5的升级也为Spring Boot、Spring Cloud提供了很是丰富的经验,Spring不仅是一个框架,已然成了一个编程生态。

相关文章
相关标签/搜索