近期在极客时间购买了小马哥的课程–《小马哥讲Spring核心编程思想》,该课程贯穿整个Spring Framework开源框架的架构设计、编程思想、Spring模块化设计的原理等课题。

学习Spring,专门开设一门专栏,在学习的过程中,坚持做笔记,了解Spring各个模块中的原理以及思想。夯实基础!坚持坚持坚持!

Spring 特性总览

之所以罗列一下Spring的所有特性,也是为了让大家了解一下Spring并非只是做IOC容器,来提供Bean的实例对象,它的具体模块做了很多事情。以下就是Spring的特性。

Spring 的特性分为:
1. 核心特性
2. 数据存储
3. Web技术
4. 框架整合与测试

我们一一罗列上述特性的细节。

核心特性

IOC容器(IOC Container)

什么是容器?容器是一种为某种特定组件的运行提供必要支持的一个软件环境。例如,Tomcat就是一个Servlet容器,它可以为Servlet的运行提供运行环境。类似Docker这样的软件也是一个容器,它提供了必要的Linux环境以便运行一个特定的Linux进程。

通常来说,使用容器运行组件,除了提供一个组件运行环境之外,容器还提供了许多底层服务。例如,Servlet容器底层实现了TCP连接,解析HTTP协议等非常复杂的服务,如果没有容器来提供这些服务,我们就无法编写像Servlet这样代码简单,功能强大的组件。早期的JavaEE服务器提供的EJB容器最重要的功能就是通过声明式事务服务,使得EJB组件的开发人员不必自己编写冗长的事务处理代码,所以极大地简化了事务处理。

Spring的核心就是提供了一个IoC容器,它可以管理所有轻量级的JavaBean组件,提供的底层服务包括组件的生命周期管理、配置和组装服务、AOP支持,以及建立在AOP基础上的声明式事务服务等。

Spring 事件(Events)

在spring容器中是通过ApplicationEvent类和ApplicationListener接口来处理事件的.如果某个bean实现了ApplicationListener接口并被部署到容器中, 那么每次对应的ApplicationEvent被发布到容器中时,都会通知该bean.这是典型的观察者模式.

spring的事件默认是同步的,即调用publisEvent()方法发布事件后, 它会处于阻塞状态, 直到onApplicationEvent接收到事件并处理完返回之后才会继续往下执行, 这种单线程同步的好处是可以进行事务管理.

资源管理(Resources)

在用Spring做开发的时候,总免不了读取各种各样的资源文件,比如说Spring的xml配置文件、属性的配置文件properties文件等。这些资源文件可能在classPath下面、web容器的上下文中、网络上等等。虽然JDK将不同来源的资源抽象成URL,通过注册不同的handler(URLStreamHandler)来处理不同来源的资源的读取逻辑(根据使用的不同协议来识别这些资源文件的来源,像“file:”、“http:”、“jar:”),但是URL没有默认定义相对ClassPath或ServletContext等资源的handler,即便我们可以注册自己的URLStreamHandler来解析特定的URL前缀(协议如classpath:),但是这需要我们了解URL的实现机制,要求比较高,并且URL也没有提供一些基本的方法,比如检查当前资源是否存在,检查当前资源是否可读等。所以,Spring为了处理不同的资源类型抽象了一个接口出来,这个接口是Resource。

  1. 资源加载

我们来看一下Spring为我们提供了哪些资源类型的地址前缀:

地址前缀 示例 对应的资源类型
classpath: classpath:com/spring/conf.xml 从类路径总加载资源,classpath:和classpath:/是等价的,都是相对于类的根路径。资源文件可以在标准的文件系统中,也可以在jar或zip的类包中
file: file:/com/spring/conf.xml 使用UrlResource从文件系统目录中装载资源,可以使用绝对或相对路径
http:// http://www.xxx.conf.xml 使用UrlResource从web服务器中装载资源
ftp:// ftp://www.xxx.conf.xml 使用UrlResource从FTP服务器中装载资源
没有前缀 com/spring/conf.xml 根据ApplicationContext具体实现类采用对应类型的Resource
  1. classpath:和classpath*:

我们可能经常在项目中看到classpath:和classpath:这两种的地址前缀,这两种地址前缀有什么区别呢?classpath:只会从第一个加载的com.spring包下查找,而classpath:则会扫描所有的com.spring包,不管是在jar中还是项目中的。这样就明白了吧。通用我们在写资源配置路径的时候还可以用Ant风格,如:

  • ?:匹配文件名中的一个字符
  • *:匹配文件名中任意个字符
  • **:匹配多层路径
  1. 资源加载器

资源加载器的父接口是ResourceLoader接口,这个接口只有一个getResource(String location)的方法,可以根据一个资源地址加载文件,它只支持带资源类型前缀的表达式,不支持Ant风格的资源路径表达式。有一个ResourcePatternResolver扩展ResourceLoader接口,定义了一个新的接口:getResources(String locationPattern),该方法支持带资源类型前缀及Ant风格的资源路径的表达式。PathMatchingResourcePatternResolver是Spring提供的一个标准的实现。我们用到的其他的获取Bean的类,都是用到了这个PathMatchingResourcePatternResolver类。我们看一下根据ResourceLoader画出来的一个类图,包含了很多IOC核心的类。

国际化(i18n)

i18n(其来源是英文单词internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称。在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改变就能够适应不同的语言和地区的需要。对程序来说,在不修改内部代码的情况下,能根据不同语言及地区显示相应的界面。在全球化的时代,国际化尤为重要,因为产品的潜在用户可能来自世界的各个角落。通常与i18n相关的还有L10n(“本地化”的简称)。

校验(Validation)

在 Web 应用中,客户端提交数据之前都会进行数据的校验,比如用户注册时填写的邮箱地址是否符合规范、用户名长度的限制等等,不过这并不意味着服务端的代码可以免去数据验证的工作,用户也可能使用 HTTP 工具直接发送违法数据。为了保证数据的安全性,服务端的数据校验是必须的。

先理清概念:

  1. JSR-303 是 JavaEE 6 中的一项子规范,又称作 Bean Validation,提供了针对 Java Bean 字段的一些校验注解,如@NotNull,@Min等。JSR-349 是其升级版本,添加了一些新特性。
  2. Hibernate Validator 是对这个规范的实现(与 ORM 框架无关),并在它的基础上增加了一些新的校验注解。
  3. Spring 本身也有一个校验接口Validator,位于 org.springframework.validation 包下,但是使用这个接口需要进行硬编码,也就是手动校验,没有提供注解进行简化。为了给开发者提供便捷,Spring 也全面支持 JSR-303、JSR-349 规范,对 Hibernate Validation 进行二次封装,在 SpringMVC 模块中添加了自动校验机制,可以利用注解对 Java Bean 的字段的值进行校验,并将校验信息封装进特定的类中。
注解名称 说明
@Null 被注解元素必须为 null
@AssertTrue 被注解元素必须为 true
@AssertFalse 被注解元素必须为 false
@Min(value) 被注解元素必须是一个值,并且不能小于指定的值
@Max(value) 被注解元素必须是一个值,并且不能大于指定的值
@DecimalMin(value) 被注解元素必须是一个数字,并且不能小于指定的值
@DecimalMax(value) 被注解元素必须是一个数字,并且不能大于指定的值
@Size(max=,min=) 被注解元素的大小必须在指定范围内
@Digits(integer,fraction) 被注解元素必须是一个数字,其值必须在指定范围内
@Past 被注解元素必须是一个过去的日期
@Future 被注解元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注解元素必须符合指定的正则表达式

数据绑定(Data Binding)

在使用servlet的时候,通过doGet和doPost方法中的HttpServletRequest对象获取参数,但是通过request对象获取的参数都是String类型的,如果前端传一个int类型的id,我们在后台使用request对象取出后要进行数据转换;如果要添加一个课程的话,在前端输入相关属性后,通过form表单传给后台,后台处理业务方法的时候,通过request获取参数,然后要封装成一个课程对象。使用SpringMVC框架之后,就不需要再进行数据的转换、封装等操作,只需要在形参列表定义类型就可以了。SpringMVC框架会自动将http请求中的参数取出来绑定到形参当中。

类型转换(Type Conversion)

Spring的类型转换系统在经历了版本升级变更之后,也随之发生了很大的变化,从3.0前的PropertyEditor体系转变到了3.0后的Converter和Formatter转换体系。这里会先从早期的PropertyEditor开始分析,然后再分析3.0后的类型转换体系;分析ProperyEditor更有助于我们对Spring内部实现机制的理解,然后通过不同的类型转换系统进行一个对比,理解版本升级所带来的意义与好处。

Spring表达式(Spring Express Language)

Spring还提供了更灵活的注入方式,那就是Spring表达式,实际上Spring EL远比以上注入方式强大,我们需要学习它。Spring EL拥有很多功能。
使用Bean的id来引用Bean。

  • 调用指定对象的方法和访问对象的属性。

  • 进行运算。

  • 提供正则表达式进行匹配。

  • 集合配置。

这些都是Spring表达式的内容,使用Spring表达式可以获得比使用Properties文件更为强大的装配功能,只是有时候为了方便测试可以使用Spring EL定义的解析类进行测试,为此我们先来认识它们。

面向切面变成(AOP)

AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

AOP技术恰恰相反,它利用一种称为”横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为”Aspect”,即切面。所谓”切面”,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

使用”横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

数据存储(Data Access)

JDBC

它是 spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装。spring 框架为我们提供了很多的操作模板类。

  1. 操作关系型数据的: JdbcTemplate HibernateTemplate

  2. 操作 nosql 数据库的: RedisTemplate

  3. 操作消息队列的:JmsTemplate

事务抽象(Transactions)

Spring框架已经成为了主流必不可少的一部分,同样在事务处理上,Spring给我们提供了一致的事务管理抽象,这个抽象是Spring最重要的抽象之一,能实现为不同的事务Api提供一致的编程模型,事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。

DAO支持(DAO Support)

DAO(Data Access Object)是用于访问数据的对象,虽然在大多数情况下将数存在数据库中,但这并不是唯一的选择,也可以将数据存储到文件中或LDAP中。DAO不但屏蔽了数据存储的最终介质的不同,也屏蔽了具体的实现技术的不同。提供DAO层的抽象可以带来一些好处:可以很容易地构造模拟对象,方便单元测试的开展;在使用切面时会有更多的选择,既可以使用JDK动态代理,又可以使用 CGLib动态代理。

Spring DAO的内容

  • Spring对多个持久化技术提供了集成支持,包括 Hibernate、 MyBatis、JPA、JDO;

  • Spring提供一个简化JDBC API操作的Spring JDBC框架。

  • Spring面向DAO制定了一个通用的异常体系,屏蔽具体持久化技术的异常,使业务层和具体的持久化技术实现解耦。

  • Spring提供了模板类简化各种持久化技术的使用。

O/R映射(O/R Mapping)

O/R映射层是持久层的一个特例,它的数据模型是对象模型(Object),存储模型是关系模型(Relational),cmp和Hibernate是对象模型到关系模型之间转换的两种不同实现。
由于对象模型和关系模型应用广泛,所以很多人错误的认为数据持久层就是对象模型到关系型数据库的转换,其实持久化的范围更广一些。
其中,数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中数据模型的统称。数据模型可以是任何数据或对象模型,存储模型可以使关系模型、XML、二进制等。
持久层(Persistence Layer),即专注于实现数据持久化应用领域的某个特定系统的一个逻辑层面,将数据使用者和数据实体相关联。

XML编列 (XML Marshalling)

对象/XML映射器或者简称O/X映射器,是一种在XML文档和对象之间互相转换的行为。这种转换过程也叫做XML编组或者XML序列化。本章将交替使用这两种术语。

在O/X映射器中,编组是指把对象序列化为XML的过程。同样,解组是指XML反序列化为对象,XML可以是DOM文档、输入输出流或者SAX处理程序。

WEB技术(Web)

Spring MVC

Spring MVC 是 Spring 提供给 Web 应用的框架设计。Spring MVC 是一个典型的教科书式的 mvc 构架,不像 Struts 等都是变种或者不是完全基于 mvc 系统的框架。

Spring MVC 角色划分清晰,分工明细,并且和 Spring 框架无缝结合。作为当今业界最主流的 Web 开发框架,Spring MVC 已经成为当前最热门的开发技能,同时也广泛用于桌面开发领域。

SockJS

WebSocket是一个相对比较新的规范,在Web浏览器和应用服务器上没有得到一致的支持。所以我们需要一种WebSocket的备选方案。
而这恰恰是SockJS所擅长的。SockJS是WebSocket技术的一种模拟,在表面上,它尽可能对应WebSocket API,但是在底层非常智能。如果WebSocket技术不可用的话,就会选择另外的通信方式。

Spring WebFlux

Spring WebFlux 是 Spring Framework 5.0中引入的新的响应式web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且非阻塞的,并且通过Reactor项目实现了Reactive Streams规范。

Spring WebFlux 用于创建基于事件循环执行模型的完全异步且非阻塞的应用程序。

(PS:所谓异步非阻塞是针对服务端而言的,是说服务端可以充分利用CPU资源去做更多事情,这与客户端无关,客户端该怎么请求还是怎么请求。)

Reactive Streams是一套用于构建高吞吐量、低延迟应用的规范。而Reactor项目是基于这套规范的实现,它是一个完全非阻塞的基础,且支持背压。Spring WebFlux基于Reactor实现了完全异步非阻塞的一套web框架,是一套响应式堆栈。

【spring-webmvc + Servlet + Tomcat】命令式的、同步阻塞的

【spring-webflux + Reactor + Netty】响应式的、异步非阻塞的

WebClient

WebClient是从Spring WebFlux 5.0版本开始提供的一个非阻塞的基于响应式编程的进行Http请求的客户端工具。它的响应式编程的基于Reactor的。WebClient中提供了标准Http请求方式对应的get、post、put、delete等方法,可以用来发起相应的请求。

WebSocket

WebSocket协议提供了通过一个套接字实现全双工通信的功能。除了其他的功能之外,它能够实现Web浏览器和服务器之间的异步通信。全双工意味着服务器可以发送消息给浏览器,浏览器也可以发送消息给服务器。

技术整合(Integration)

远程调用(Remoting)

Remoting实际上是一种企业分布式计算的组件。在同一服务器(Java虚拟机)内进行调用的服务(或类)并不需要把自己暴露为一种远程服务; 但是,如果你需要与一个外部程序(在不同的服务器上或在一个不同的组织中)进行通讯的话,那么,必须把它实现为一个远程服务。Spring框架为把业务类 暴露为远程服务提供了一种独特而灵活的方式。

Spring Remoting架构的核心是服务对象,这些对象其实是一些POJO,也称作Spring bean。Spring框架能够把这些服务对象与基础结构细节(例如它们暴露为远程服务的方式)隔离开来;这样以来,开发者就可以专注于实现服务对象的业 务接口而不是牵涉到这些细节中去。

这个Remoting模型提供了对业务服务的远程抽象。它负责编排和反编排方法参数并且还负责处理服务方法中抛出的任何异常—使用未检查的RemoteAccessException异常对它们进行包装。为了实现各种服务,Spring使用了若干设计模式。例如,它使用代理设计模式把你对HTTP POST请求的调用翻译成指向输出服务的URL。

Spring目前提供了对RMI、HttpInvoker、Hessian、Burlap及WebService等Remoting技术的集成。Spring屏蔽了这些实现技术的差异,用户只需开发简单的Java对象(Plain Old Java Objects,POJO)然后按照Spring规定的格式进行配置文件的编写即可。

Java消息服务(JMS)

在一些场景下RPC的同步方式可能不太适合业务逻辑的处理,并且这种方式在某些场景下会导致业务的紧耦合。
基于异步交互模型的JMS解决了RPC产生的紧耦合问题,它提供了一个可以通过网络访问的抽象消息队列。

Java连接架构(JCA)

定义一个标准的的架构来实现Java EE平台与非Java EE的企业信息系统(EIS)相连接。这些EIS系统包括:ERP系统, 大型机事务处理(TP),数据库和消息系统等。
这个连接器架构定义了一组可扩展、安全、事务的机制能够实现EIS与应用服务器和企业应用程序相集成。
这个连接器架构还为访问EIS系统定义了一个公共客户端接口(CCI) 。这个CCI定义了一个客户端API用于与非Java EIS系统相交互。

Java管理扩展(JMX)

JMX是Java Management Extensions的缩写,意为Java管理扩展,是一个标准也是一个框架,用来监控和管理JVM上面的资源,例如我们用jvisualvm监控远程的JVM时,远程需要开启JMX;

JMX作为一个标准和框架,要实现JMX编程必须基于其架构,架构就是与其相关的一些概念或架构分层;

JMX有一个MBean / 管理组件的概念,MBean是Management Bean的缩写,是对JVM上面所有资源的抽象,MBean作为一种Java对象,可以通过MBean的属性和方法访问JVM上面的各种资源;

JMX的架构由 分布层、代理层、设备层 组成;

Java邮件客户端(Email)

JavaMail,顾名思义,提供给开发者处理电子邮件相关的编程接口。它是Sun发布的用来处理email的API。它可以方便地执行一些常用的邮件传输。

  虽然JavaMail是Sun的API之一,但它目前还没有被加在标准的java开发工具包中(Java Development Kit),这就意味着你在使用前必须另外下载JavaMail文件。除此以外,你还需要有Sun的JavaBeans Activation Framework (JAF)。JavaBeans Activation Framework的运行很复杂,在这里简单的说就是JavaMail的运行必须得依赖于它的支持。在Windows 2000下使用需要指定这些文件的路径,在其它的操作系统上也类似。

  JavaMail是可选包,因此如果需要使用的话你需要首先从java.sun.com下载。目前最新版本是JavaMail1.4,使用JavaMail的时候需要Javabean Activation Framework的支持,因此你也需要下载JAF。安装JavaMail只是需要把他们加入到CLASSPATH中去,如果你不想修改CLASSPATH的话,可以直接把他们的jar包直接copy到JAVA_HOME/lib/ext下。这样JavaMail就安装好了。

  JavaMail包中用于处理电子邮件的核心类是:Session,Message,Address,Authenticator,Transport,Store,Folder等。Session定义了一个基本的邮件会话,它需要从Properties中读取类似于邮件服务器,用户名和密码等信息

本地任务/本地调度(Tasks)

Spring内部有一个task是Spring自带的一个设定时间自动任务调度,提供了两种方式进行配置,一种是注解的方式,而另外一种就是XML配置方式了。注解方式比较简洁,XML配置方式相对而言有些繁琐,但是应用场景的不同,两者又各有优点,所以具体使用还是根据需求来划分。因为任务调度这样的需求,通常改动都是比较多的,如果用注解的方式改动就变得麻烦了,必须去重新编译。所以更多的时候我选择用XML配置的方式。

缓存抽象(Caching)

抽象的核心是将缓存应用于Java方法,从而减少了基于缓存中可用信息的执行次数。也就是说,每次调用目标方法时,抽象都会应用缓存行为检查方法是否已经为给定的参数执行。如果有,则返回缓存的结果,而不必执行实际的方法;如果没有,则执行方法,缓存结果并返回给用户,以便在下次调用方法时返回缓存的结果。这样,对于给定的一组参数,昂贵的方法(CPU或IO绑定)只能执行一次,并且结果可以重用,而不必实际再次执行该方法。缓存逻辑被透明地应用,没有任何对调用程序的干扰。

就像Spring Framework中的其他服务一样,缓存服务是一种抽象(不是缓存实现),需要使用实际存储来存储缓存数据 – 也就是说,抽象使开发人员不必编写缓存逻辑 但不提供实际的存储。 这种抽象由org.springframework.cache.Cache和org.springframework.cache.CacheManager接口实现。

这个抽象的一些实现可以直接使用:基于JDK java.util.concurrent.ConcurrentMap的缓存(即默认的缓存是基于JVM的ConcurrentMap),Ehcache 2.x,Gemfire缓存,符合Caffeine和JSR-107的缓存(例如Ehcache 3.x)。 有关插入其他缓存存储/提供程序的更多信息,请参阅插入不同的后端缓存。

对于缓存声明,抽象提供了一组Java注释:

@Cacheable 触发数据存储于缓存

@CacheEvict 触发删除缓存条目

@CachePut 更新缓存而不会干扰方法执行

@Caching 重新组合要在方法上应用的多个缓存操作

@CacheConfig 在类级别共享一些常见的缓存相关设置

Spring测试(Testing)

模拟对象(Mock Objects)

测试驱动开发是敏捷开发中重要部分。在现实项目中,开发人员通常希望减少对其它模块的依赖,把测试的单元与系统其它单元隔离。本文介绍敏捷开发并探讨测试驱动开发的重要性。对 mock 技术进行理论分析,并结合当前流行的 mock 软件如 jMock 和 EasyMock 等,展示测试驱动开发实例并进行比较。

TestContext框架(TestContext Framework)

TestContext 测试框架的核心由 org.springframework.test.context 包中三个类组成,分别是TestContext 和TestContextManager 类以及TestExecutionListener 接口。

每次测试都会创建TestContextManager。TestContextManager管理了一个TestContext, 它负责持有当前测试的上下文。TestContextManager还负责在测试执行过程中更新TestContext的状态并代理到TestExecutionListener, 它用来监测测试实际的执行(如提供依赖注入、管理事务等等)

TestContext
TestContext:封装测试执行的上下文,与当前使用的测试框架无关。

TestContextManager
TestContextManager:SpringTestContext Framework的主入口点, 负责管理单独的TestContext并在定义好的执行点上向所有注册的TestExecutionListener发出事件通知: 测试实例的准备,先于特定的测试框架的前置方法,迟于后置方法。
TestExecutionListener
TestExecutionListener:定义了一个监听器API与TestContextManager发布的测试执行事件进行交互,而该监听器就是注册到这个TestContextManager上的。

Spring提供了TestExecutionListener的三个实现, 他们都是使用默认值进行配置的(通过@TestExecutionListeners注解):DependencyInjectionTestExecutionListener、DirtiesContextTestExecutionListener及TransactionalTestExecutionListener,他们对测试实例提供了依赖注入支持,处理@DirtiesContext注解,并分别使用默认的回滚语义对测试提供事务支持。

DependencyInjectionTestExecutionListener:该监听器提供了自动注入的功能,它负责解析测试用例中@Autowried 注解并完成自动注入;

DirtiesContextTestExecutionListener:一般情况下测试方法并不会对Spring 容器上下文造成破坏(改变Bean 的配置信息等),如果某个测试方法确实会破坏Spring 容器上下文,你可以显式地为该测试方法添加@DirtiesContext 注解,以便Spring TestContext 在测试该方法后刷新Spring 容器的上下文,而DirtiesContextTestExecutionListener 监听器的工作就是解析 @DirtiesContext 注解;

TransactionalTestExecutionListener:它负责解析@Transaction、@NotTransactional以及@Rollback 等事务注解的注解。@Transaction注解让测试方法工作于事务环境中,不过在测试方法返回前事务会被回滚。你可以使用@Rollback(false) 让测试方法返回前提交事务。而@NotTransactional 注解则让测试方法不工作于事务环境中。此外,你还可以使用类或方法级别的 @TransactionConfiguration注解改变事务管理策略

@TestExecutionListeners
用来注册TestExecutionListener

@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,DirtiesContextTestExecutionListener.class})

Spring MVC 测试(Spring MVC Test)/Web 测试客户端(Web TestClient)

在使用springboot进行开发时,单元测试是必要的,当你建立一个spring项目时,它会为我们自己生成一个测试项目,当你的项目开始过程中,测试用例是同时要进行的,我们在进行WEB层的集成测试时,可以使用spring为我们提供的WebTestClient工具,非常方便,提供了基于restful的各种类型和状态!