购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.3 Spring Boot实战内容和案例

作为Spring家族的重要一员,Spring Boot的入门虽然比较简单,但在实际开发过程中要想将它应用自如并不容易,需要一个系统化的、由浅入深的学习和理解过程,才能更好地将其应用到工作中。而本书的定位就是提供一份实战指南,对日常开发过程中用到的Spring Boot各项技术给出完整的实战内容讲解和案例分析。

在本节中,我们将系统梳理Spring Boot实战内容,并把这些内容划分为核心容器、Web服务、数据访问、内置缓存、并发编程、监控和扩展六大主题。同时,我们也将给出与这些主题相关的实战案例描述。

1.3.1 核心容器

针对核心容器,我们将深入讨论Spring所具备的依赖注入和面向切面编程这两项基础功能。

1. 核心容器的实战内容

(1)依赖注入

对于依赖注入而言,Spring容器为开发人员提供了字段注入、构造器注入和Setter方法注入这三种实现方式。不同的依赖注入方式各有其优缺点,我们将对它们进行详细的分析,并给出Spring依赖注入的实现原理。

当讨论如何管理对象之间的依赖关系时,循环依赖是一个不可回避的话题。Spring的依赖注入机制在解决循环依赖问题时采用了三级缓存机制。这是Spring在设计和实现上的一大特色,也是开发人员在面试过程中经常遇到的话题,我们将对三级缓存结构以及循环依赖解决方案进行深入剖析。

从实战角度讲,把握Bean的作用域、灵活使用注解配置、设置组件扫描范围以及对不同配置进行性能分析是日常使用Spring依赖注入时所需要掌握的一些开发技巧。

(2)面向切面编程

对于AOP而言,Spring框架提供了连接点、通知、切点等核心概念,以及@Before、@After、@Around、@AfterThrowing和@AfterReturning等注解。通过这些注解,开发人员可以很轻松地在业务代码中嵌入切面。

AOP的使用虽然简单,但它背后的实现原理并不简单。想要理解AOP的原理就需要对动态代理机制有深入的了解。Java世界中典型的JDK动态代理和CGLIB动态代理,在Spring中也都得到了广泛应用。我们将基于这些代理机制来详细分析Spring AOP的实现原理。

从实战角度讲,活用切点表达式、确保类内方法调用能够应用代理、避免代理机制引起多次初始化过程以及优先使用JDK动态代理是常见的开发技巧。

2. 核心容器的实战案例

在核心容器部分,我们将给出三个实战案例,即消除循环依赖案例、Spring AOP案例以及Spring AOP代理机制对性能的影响案例。

针对如何消除循环依赖,业界也存在一些常见的做法。我们将通过代码实例给出消除循环依赖的三种实现方法,即提取中介者、转移业务逻辑以及使用回调机制。

Spring AOP案例演示如何在Spring中使用面向切面编程技术。而AOP代理机制对性能的影响案例的目标是分析各种动态代理机制对于Spring执行性能的影响。我们将分别针对JDK动态代理和CGLIB动态代理给出对应的性能评估,并明确推荐使用的代理机制。

1.3.2 Web服务

在当下的互联网应用程序中,前后端分离的开发模式大行其道,Web服务是开发人员使用Spring Boot实现HTTP端点的基本手段。这部分内容涉及的技术体系非常丰富,我们把这些技术体系按实战方向分成两大部分,即轻量级Web服务和响应式Web服务。

1. Web服务的实战内容

(1)轻量级Web服务

对于轻量级Web服务开发而言,传统的Spring WebMVC仍然是目前主流的技术体系,我们可以使用Controller来暴露HTTP端点,并通过RestTemplate工具类来实现对远程服务的访问。

我们知道这种基于HTTP的请求-响应模式采用的是RESTful架构风格。但是请注意,真正的RESTful风格存在一个成熟度模型,代表最高成熟度等级的并不是我们日常所使用的WebMVC,而是HATEOAS(Hypermedia As The Engine Of Application State,基于超媒体的应用状态引擎)。Spring也专门为实现HATEOAS提供了Spring HATEOAS框架。

针对前后端分离的开发场景,如何设计合理且高效的交互Web API是前端和后台开发人员日常开发工作的一大难点和痛点。传统的RESTful风格能够很好运作的前提是提取资源的需求和API的设计之间能够得到匹配。如果这一条件无法满足,那么就会出现前端无法预判响应的数据格式、无法根据请求控制对应的返回结果以及需要发送多次请求等诸多问题。GraphQL为这些问题提供了解决方案,而Spring家族的Spring GraphQL框架也已经正式成为Spring顶级项目。

从实战角度讲,如何基于RESTful风格设计合理的HTTP端点、如何基于HATEOAS开发自解释型Web API,以及如何使用GraphQL替代RESTful API,需要开发人员有相应的设计方法和实现技巧。

(2)响应式Web服务

随着Spring 5的正式发布,我们迎来了响应式编程(Reactive Programming)的全新发展时期。响应式编程能够提高系统的弹性。Spring在Project Reactor这款响应式编程框架的基础上开发了Spring WebFlux框架。相较Spring WebMVC,Spring WebFlux能够为我们实现异步、非阻塞的远程交互过程。

在响应式的世界中,关于Web服务还有一个重要的话题,即网络协议。我们知道HTTP是一款典型的请求-响应式的应用层协议。而请求-响应模式在很多应用场景中存在局限性,也无法与响应式编程体系进行整合。在这个背景下就诞生了RSocket协议,该协议提供了四种不同的Web交互模式,并且可以与响应式编程技术完美融合。Spring目前已经全面拥抱RSocket协议,并专门提供了Spring RSocket框架。

从实战角度讲,使用非阻塞式Web服务提升系统性能、结合响应式Web服务和响应式数据访问技术构建全栈响应式服务体系,以及使用RSocket替代HTTP等开发技巧,可以直接应用于日常开发过程中,并实现系统性能的提升和交互方式的改进。

2. Web服务的实战案例

可以说,开发Web服务是Spring Boot框架最主要的应用场景,因此本书提供了大量的案例来充分展示Web服务的开发过程,包括Spring WebMVC案例、Spring HATEOAS案例、Spring GraphQL案例、Spring WebFlux案例以及Spring RSocket案例。

对于使用Spring Boot开发Web服务而言,正确使用Spring WebMVC是基础。为此,我们将通过一个案例来展示基于WebMVC构建RESTful API的实现方法。

在Spring WebMVC的基础之上,Spring HATEOAS案例的价值在于为我们提供超媒体(Hypermedia)应用程序的开发经验。基于超媒体中的链接机制,你会发现开发自解释Web API并没有看上去那么难。

2021年7月,Spring GraphQL发布了1.0.0版本,正式成为Spring家族的顶级项目。Spring GraphQL构建在GraphQL Java的基础之上,是原有的GraphQL Java Spring框架的替代版本,为开发人员使用GraphQL提供了多项技术支持。我们将通过一个精简但又完整的案例来演示最新版本Spring GraphQL的功能特性。

在开发响应式系统时,首先需要掌握的是响应式编程框架。Spring内置的响应式编程框架是Project Reactor。在掌握Project Reactor的基础上,我们进一步通过案例来展示使用Spring WebFlux开发响应式Web服务的实现过程。开发人员可以通过使用注解和函数式编程这两种开发模式来实现响应式Web服务,并基于全新的WebClient工具类实现非阻塞式的远程调用过程。

关于Web服务的最后一个案例是针对RSocket这款全新的网络通信协议给出对应的实践技巧。我们将引入整合了RSocket协议的Spring RSocket框架,并基于该框架实现传统的请求-响应模式,以及其他多种交互方式。

1.3.3 内置缓存

对于互联网应用而言,缓存可以说是一种基础技术组件。缓存的应用非常广泛,开发人员可以使用位于应用程序内部的本地缓存,也可以使用位于独立服务器上的分布式缓存。从3.1版本开始,Spring为开发人员提供了一个非常好用的缓存组件。在本书中,针对Spring内置缓存的讨论将分成两大部分,即针对通用场景的系统缓存,以及针对安全管理场景的认证缓存。

1. 内置缓存的实战内容

(1)系统缓存

Spring的缓存机制非常灵活,提供了一组包括@Cacheable、@CachePut和@CacheEvict在内的注解来简化系统缓存的使用过程,可以通过这些注解对容器中的任意Bean或者Bean的方法添加缓存功能。开发人员在使用系统缓存时,需要做的事情就是指定缓存键,并对缓存功能进行配置。

作为一款通用的技术组件,缓存的实现方式也有很多种,包括支持分布式场景的Redis和Hazelcast,以及支持应用程序本地缓存的EhCache、Guava、Caffeine等。Spring作为一款主流的开源框架,通过对缓存操作进行高度抽象,为开发人员提供一套统一的API。这种针对缓存的抽象机制值得我们深入学习。因此,本书中也会对Cache、CacheManager、CacheInterceptor等Spring缓存中的核心组件进行源码级别的剖析。

从实战角度讲,Spring缓存提供的统一编程API有时候并不能够满足我们的需求。所以,自定义缓存注解、自定义缓存键生成器,以及自定义Cache和CacheManager是日常开发过程中经常用到的开发技巧。

(2)认证缓存

Spring中的认证缓存可以认为是系统缓存在安全管理领域的一种具体的应用场景。想要使用认证缓存,我们首先需要对Spring家族中另一款具有代表性的安全框架Spring Security有一定的了解。Spring Security中内置了一套完整的认证和授权机制,开发人员可以通过引入认证缓存提高安全性处理的性能。

同样,认证缓存作为系统缓存的具体应用,与Spring Security框架中的用户认证过程紧密结合并完成全流程的缓存操作,也能为开发人员更好地应用Spring缓存机制提供参考。因此,我们也将对Spring Security框架中的UserDetails、Authentication、UserCache等核心对象展开原理分析。

和系统缓存一样,认证缓存的使用也比较简单,但通常需要开发人员基于自身业务实现自定义的扩展组件。从实战角度讲,如何实现定制化UserDetails以及对应的AuthenticationProvider是我们需要掌握的实战能力。

2. 内置缓存的实战案例

针对Spring内置的缓存组件,我们将分别针对系统缓存和认证缓存实现两个实战案例,即Spring缓存案例和Spring Security认证缓存案例。

在高并发场景下,缓存机制可以很好地解决系统性能瓶颈问题。Spring缓存内部集成了一批具有代表性的第三方缓存工具,我们将通过一个案例来分析如何使用Spring缓存应对高并发请求场景。

在安全性处理场景中,如果用户认证数据的获取和处理过程需要与数据库进行交互,那么这种交互过程很可能对系统性能带来负面影响。这时候,解决这个问题的一种有效方案是将用户身份验证缓存特定的时间长度。基于Spring提供的认证缓存,我们也将对该场景的处理过程给出案例。

1.3.4 数据访问

无论互联网应用还是传统软件,对于任何一个系统而言,数据的存储和访问都是不可缺少的。数据访问层的构建可能会涉及多种不同形式的数据存储媒介,本书关注的是最基础也是最常用的数据存储媒介,即关系型数据库。Spring Boot对关系型数据库访问的支持包括两大部分内容,即基于JDBC(Java DataBase Connectivity,Java数据库连接)规范的Spring JDBC组件和支持ORM(Object Relational Mapping,对象关系映射)的Spring Data组件。

1. 数据访问的实战内容

(1)Spring JDBC

针对关系型数据库,Java世界中应用最广泛的就是JDBC规范,但JDBC规范是一种偏底层的实现技术,不适合直接面向业务开发。Spring框架基于JDBC规范,提供了一整套的解决方案,包括常用的JdbcTemplate模板工具类,以及在JdbcTemplate基础上构建的能够进一步简化数据访问操作的SimpleJdbcInsert等组件。

在Spring中,以-Template结尾的模板工具类应用非常广泛,而这些模板工具类的设计和实现最大限度地发挥了模板方法设计模式的优势,并基于回调机制解决了原生JDBC等组件所面临的复杂性问题。JdbcTemplate作为一种典型的模板工具类,其实现过程非常具有代表性,为开发人员如何对底层框架进行封装和扩展提供了范本。因此,本书也将对JdbcTemplate的源码展开讨论,讲解其中的设计理念和实现技巧。

从实战角度讲,Spring JDBC的使用涉及很多技术细节,例如优化事务隔离等级、优化Fetch Size、优化连接池配置、选择合适的Statement、使用批处理、选择合适的提交模式等。针对这些技术细节,我们都将给出对应的实战技巧。

(2)Spring Data

事实上,JdbcTemplate是相对偏底层的一个工具类。作为系统开发最重要的基础功能之一,数据访问层组件的开发方式在Spring Boot中也得到了进一步的简化,并充分发挥了Spring家族中另一个重要成员Spring Data的作用。Spring Data是基于Repository架构模式抽象出来的一套统一的数据访问组件,是一款支持JPA等多种数据访问规范的ORM框架。

在使用Hibernate等ORM框架时,会碰到经典的N+1性能问题。针对该问题存在多种解决方案,常见的包括JOIN FETCH和Entity Graph机制。对于JOIN FETCH,可以使用JPA查询语句和Criteria API这两种实现方式;而对于Entity Graph,可以使用Named Entity Graph和Dynamic Entity Graph。

从实战角度讲,通过统计找到数据访问瓶颈并使用延迟加载减少数据库访问是常见的开发技巧。而另一种常见的开发技巧就是使用多级缓存提升数据访问性能。诸如Mybatis和Hibernate等主流ORM框架都提供了多级缓存机制来确保对内存对象的合理管理。

2. 数据访问的实战案例

针对Spring提供的数据访问功能,我们将分别基于Spring JDBC以及Spring Data JPA给出相应的案例分析。

Spring JDBC中,除了JdbcTemplate之外,还存在一大批非常有用的工具类,包括Named-ParameterJdbcTemplate、SimpleJdbcTemplate、SimpleJdbcInsert和SimpleJdbcCall等。我们将基于一个案例来演示如何使用JdbcTemplate和SimpleJdbcInsert实现数据的高效查询和插入。

Spring Data中所包含的技术组件也非常丰富,我们主要针对Spring Data JPA这款框架给出案例分析。JPA只是一种规范,而不是具体的实现。而Hibernate框架遵循JPA规范,并且还有一些自己的附加特性。在使用JPA规范时,将首选Hibernate这款老牌的ORM框架。

1.3.5 并发编程

对于任何请求-响应模式下的处理过程,都需要关注请求的响应能力。对于Web请求而言,我们希望服务端能够快速返回处理结果,从而提高系统的响应能力。而Spring框架也针对这一诉求给出了它的解决方案,这就是并发编程模型。Spring对于并发编程模型的支持包括两个方面。一方面,Spring提供了@Async注解来实现通用的异步编程能力,并提供了WebAsyncTask组件来实现面向Web的异步处理机制。另一方面,Spring还提供了两个更高层级的并发编程工具类,即任务执行器TaskExecutor以及任务调度器TaskScheduler。

1. 并发编程的实战内容

(1)Spring Async

异步处理的主要优势是调用方不必等待被调用方完成执行过程,因为可以在一个单独的线程中执行一个方法。我们知道,JDK为开发人员提供了Future、CompletableFuture等支持异步编程的实现工具。而Spring异步编程模型在此基础上提供了一个全新的@Async注解,该注解可以与JDK中的Future机制以及线程池进行无缝整合。

Spring的@Async注解是通用的,我们可以用它来完成针对任意场景的异步处理流程。随着Spring Boot的诞生,特定于Web请求处理过程,也出现了WebAsyncTask这一专门的异步任务组件。相较@Async注解,WebAsyncTask为开发人员提供了更灵活的异步任务处理机制。

请注意,异步编程模型是一个相对复杂的话题,很多开发人员只会简单地使用@Async注解,而不知道其实现原理,这样就可能导致错误地使用该注解。本书将通过分析Spring的源码来深入理解@Async注解背后的实现原理,避免误用。

从实战角度讲,Spring Async机制已经为开发人员提供了良好的开发体验。但是该机制本质上也是对JDK中Future机制的封装和扩展,而随着JDK版本的演进,内置的Future机制也在不断地发展和增强。因此,灵活使用多种Future机制是一种开发技巧。同时,异步编程的背后是对系统线程资源的利用,所以合理设置线程池也是开发人员需要注意的一个实战点。

(2)Spring任务执行器和调度器

JDK中自带的执行器(Executor)组件使用起来非常方便,本质上是在所有内部线程管理任务上提供了一个抽象层。而Spring提供TaskExecutor接口作为Executor的扩展,包含了一大批非常有用的实现类。我们会在介绍这些实现类基本功能的同时,给出对TaskExecutor运行原理的分析。

有时候,我们需要以固定的时间间隔执行任务,这就需要引入任务调度的概念。Spring专门针对任务调度场景提供了TaskScheduler组件。基于Spring,我们将看到如何使用@Scheduled注解来对任务进行调度。同样,我们也将对该注解的实现原理进行讲解。

从实战角度讲,Spring框架分别针对不同的应用场景提供了SimpleAsyncTaskExecutor、SyncTaskExecutor、ConcurrentTaskExecutor、ThreadPoolTaskExecutor等TaskExecutor。根据具体需求,灵活使用多种TaskExecutor是一项开发技巧。同时,Spring框架中的@Scheduled注解功能也十分强大,我们可以通过使用各种表达式来制定不同的调度策略。

2. 并发编程的实战案例

针对Spring的并发编程能力,我们将给出两个面向不同应用场景的案例分析,即Web异步处理案例分析、基于代理的异步执行模型案例分析。

Spring的@Async注解提供的是一种通用的异步编程模式,可以通过@EnableAsync注解来启用该功能。而针对Web异步处理需求和场景,我们可以使用WebAsyncTask组件,该组件为开发人员提供了更灵活的异步任务处理流程,并内置了异步回调、超时处理和异常处理机制。我们将通过模拟异步任务执行超时等异常场景来演示WebAsyncTask的各项使用技巧。

Spring的@Async注解本质上是基于动态代理机制实现的,本书也会对这一实现机制进行详细讨论。而在解释@Async注解的具体原理之前,我们通过一个基于代理的异步编程模型案例来实现一套自定义的、类似@Async注解的异步执行组件,以便更好地理解Spring框架中与异步执行模型相关的设计思想和实现机制。

TaskExecutor和TaskScheduler这两个工具组件的使用都比较简单,我们会在这两个案例中穿插对它们的使用方式的具体描述。

1.3.6 监控和扩展

作为新一代开发框架,相较传统Spring,Spring Boot提供了更为全面的技术支持。在本书中,我们将从两个维度讨论Spring Boot的创新型功能特性。首先,Spring Boot为开发人员提供了一个非常有特色的主题,这个主题就是系统监控。其次,作为Spring家族中核心的开发框架之一,Spring Boot实际上也形成了一个生态系统,我们将对它的生态扩展性展开讨论。

1. 监控和扩展的实战内容

(1)系统监控

系统监控是Spring Boot中引入的一项全新功能,对于管理应用程序运行时状态非常有用。Spring Boot Actuator组件是承载系统监控功能的组件,通过一系列HTTP端点提供系统监控功能。

对于系统监控而言,可视化管理界面是必不可少的。Spring Boot基于Actuator组件提供的监控端点专门实现了Admin Server组件,用于监控基于Spring Boot开发的应用程序。

从实战角度讲,监控的目的是发现系统中存在的性能问题并找到对应的解决方案。在Spring Boot中,通过替换默认组件提升系统性能是一项最佳实践。同时,我们也可以使用PerformanceMonitorInterceptor拦截器以及自定义的性能度量指标来定制性能的跟踪和处理流程。

(2)生态扩展

关于系统扩展性,开发人员可以基于Spring Boot提供的Starter机制来将业务系统与Spring Boot进行集成。事实上,诸如Apache ShardingSphere等业界知名的开源框架都可以使用对应的Spring Boot Starter组件,从而方便我们基于Spring Boot来使用这些框架。

作为Spring Cloud框架的基础,Spring Boot也在微服务系统的构建过程中扮演重要角色,Spring Cloud技术体系下的单个微服务实际上就是一个Spring Boot应用程序。

云原生是当下技术发展的热点,Spring也提供了专门针对云原生架构的Spring Native框架。Spring Native基于GraalVM虚拟机技术,为开发人员提供了更快的启动时间以及更少的内存占用。

对于Spring Boot应用程序而言,测试是一个难点,也是经常被忽略的技术。当一个应用程序涉及数据层、服务层、Web层以及各种外部服务之间的交互关系时,Spring Boot为我们提供了全面的测试解决方案来保证服务的正确性和稳定性。

2. 监控和扩展的实战案例

针对Spring Boot的系统监控和生态扩展主题,我们将给出一系列案例分析,包括扩展Actuator端点案例分析、自定义Actuator端点案例分析、Admin Server系统监控案例分析、基于Starter集成Spring Boot案例分析、Spring微服务架构案例分析、Spring Native案例分析以及Spring Boot测试案例分析。

Spring Boot Actuator组件默认提供了一系列监控端点,最常用的就是info端点和health端点,我们将通过案例介绍如何对这些端点进行扩展。而有时候,Spring Boot提供的默认端点不一定能够满足业务需求,我们也可以实现自定义Actuator端点。

对系统性能进行可视化监控一直是一个难题,但Spring Boot Admin Server的出现为我们提供了简单好用的解决方案。我们可以通过Admin Server监控系统运行时的各项关键指标。

在基于Starter集成Spring Boot的案例分析中,我们的分析方式不是自己从零实现一个Spring Boot Starter组件,而是参考业界主流的开源框架,通过源码解析来深入理解Spring Boot Starter的实现方式。

关于微服务架构,我们将引入Spring家族中的Spring Cloud框架。因为该框架所包含的技术组件非常丰富,我们无法一一展开讲解,所以重点关注的是Spring Boot在构建微服务系统时发挥的作用。

Spring Native的诞生为Spring框架适应云原生时代的发展提供了助力。通过案例,我们将基于Spring Native框架打造更适合Spring的原生镜像。

最后的Spring Boot测试案例分析中,我们将基于Spring Boot提供的一组强大的测试注解来对应用程序的数据访问层和Web服务层分别开展系统化的测试,这些测试方法和技术都可以复用到Spring Boot的各个测试场景中。 Zqg2lKDSs2fWfiEAuGPdi64t1WajaSYCFzfCFxb9kWz/65K54PIt4bnWqqtiR9EX

点击中间区域
呼出菜单
上一章
目录
下一章
×