在这里插入图片描述

Spring Boot 2.7.0、2.6.8、25.14发布,2.5.x停止OSS支持。
本文已被https://yourbatman.cn收录;女娲Knife-Initializr工程可公开访问啦;程序员专用网盘https://wangpan.yourbatman.cn;技术专栏源代码大本营:https://github.com/yourbatman/tech-column-learning;公号后台回复“专栏列表”获取全部小而美的原创技术专栏

你好,我是方向盘(YourBatman)。笔者的公号是保留地,只分享原创,不转载、不发商务广告!

📚前言

北京时间2022-05-19,Spring Boot 2.7.0正式发布。回忆一下上次发版笔者也忘了,毕竟这节奏堪比JDK,真难顶。还好,最近的几个大版本我都有追,这里一并整理出来,方便你不用关注我的号就可以直接看全:

一年2个中型版本的节奏(5月份+11月份),Spring Boot节奏保持得很好。这个在上篇文章里也有“预测”:
在这里插入图片描述
值得注意的是:Spring Boot 2.5.x停止的是免费技术支持,关于Spring的Pivot OSS Support策略,可参照笔者之前写的文章,有详细解释。

所属专栏
相关下载
版本约定
  • Spring Boot 2.7.0

✍正文

https://start.spring.io到IDEA创建项目对话框,都能看到Spring Boot已开始首推最新版本:
在这里插入图片描述
在这里插入图片描述

Release Notes

相较于Spring Boot 2.6.x版本改动的不温不火,此版本有比较多新功能和改进,可圈可点,一起来看下。

✌对Auto-configuration的改变

面试时我常会问一个问题:传统Spring和Spring Boot有什么区别和联系?其中自动配置四个字被说出来的次数最多,是的,这是Spring Boot最大的特点之一,甚至没有之一。这一次,竟对这个从1.0版本就存在的机制“动刀”了。

此次改变在功能上虽然没有什么,但改动的文件是非常之多的。Spring Boot团队毫不手软,可谓大刀阔斧。这些改变主要表现在这两个方面:

自动配置注册机制

通过spring.factories加载自动配置类的方式成为过去式(弃用从spring.factories加载自动配置类),采用全新的方式加载自动配置类:需要被自动加载的类写在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件里,每一行是配置类的全类名。
在这里插入图片描述
org.springframework.boot.autoconfigure.AutoConfiguration.imports文件内容:
在这里插入图片描述

Tips:由于Spring Boot 2.7.0才刚发布,IDEA对此文件的支持还并没有那么的好(点击全类名无法实现跳转)。但我敢预测,IDEA在下个中版本就会支持了。

这么一来,spring.factories文件的内容就非常少了:对比一下
在这里插入图片描述
值得注意的是:为了向后兼容,spring.factories加载自动配置类的方式依旧是好使的。这一点从源码处也能看出来本次改动只是“增量形式”的改动,100%向下兼容:
在这里插入图片描述

新增@AutoConfiguration注解

这是2.7.0版本后推荐的自动配置类注解,在此之前,普通配置类和自动配置类都使用@Configuration注解,有了它这下就好区分了,语义更加清晰。

/**
* Since: 2.7.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore
@AutoConfigureAfter
public @interface AutoConfiguration {

	@AliasFor(annotation = Configuration.class)
	String value() default "";
	@AliasFor(annotation = AutoConfigureBefore.class, attribute = "value")
	Class<?>[] before() default {};
	@AliasFor(annotation = AutoConfigureBefore.class, attribute = "name")
	String[] beforeName() default {};
	@AliasFor(annotation = AutoConfigureAfter.class, attribute = "value")
	Class<?>[] after() default {};
	@AliasFor(annotation = AutoConfigureAfter.class, attribute = "name")
	String[] afterName() default {};
	
}

对此注解的解释:它是@Configuration、@AutoConfigureBefore、@AutoConfigureAfter三个注解结合体,以一顶三
在这里插入图片描述
这么来看@AutoConfiguration并非什么新物种,只是可以和普通配置类区分开,语义上更加的清晰了,足以见得Spring团队在规范方面的追求,是我们学习的榜样。当然喽,最重要还是希望你在使用时遵守“新规范”,以谢人家的一番苦心。

Tips:标注@AutoConfiguration注解的类也必须放进META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件里才算自动配置类,否则也只是普通配置类而已

✌@SpringBootTest属性优先级改变了

单元测试场景下,我们常常需要自定义一些k-v属性值以完成相关case的测试。Spring Boot提供了@SpringBootTest注解的properties、args属性以及@TestPropertySource注解,可以非常方便的向Environment里放k-v属性值,这也属于一类PropertySource属性源(统称为测试属性源)。

PropertySource属性源的顺序决定着(相同key的)哪个值最终生效,此规则在Spring Boot 2.7.0版本发生了改变:通过@SpringBootTest属性或@TestPropertySource添加的测试属性源现在被放在命令行(属性源)之上

言外之意:在2.7.0版本之前,测试属性源优先级并没有命令行属性源高

为了加深理解,最好的方式就是用代码验证一把。

代码示例

下面代码使用Spring Boot 2.6.x和Spring Boot 2.7.0版本进行对比。

准备“测试用例”:

@TestPropertySource("classpath:yourbatman-test.txt")
@SpringBootTest(properties = {"name=YourBatman", "age=18"}, args = {"name=YourBatman_CL", "age=18_CL"})
class ApplicationTests {

    @Autowired
    private ConfigurableEnvironment environment;

    @Test
    void contextLoads() {
        System.out.println(environment.getProperty("name"));
        System.out.println(environment.getProperty("age"));

        System.out.println(environment.getPropertySources());
    }
}

属性文件:
在这里插入图片描述
youbatman-test.txt文件内容:

name=YourBatman_sc-test
age=18_sc-test

分别在两个版本环境下运行,情况如下。

Spring Boot 2.6.x版本,运行结果:

YourBatman
18

在Spring Boot 2.7.0版本,运行结果:

YourBatman
18

咦,结果竟然一毛一样。难道规则改了个寂寞?下面咱来看看两个版本到底有啥区别:

Environment里PropertySource的顺序 :正如上面说的那样,2.7.0改变了这种顺序,也就是@SpringBootTest属性(Inlined Test Properties)和@TestPropertySource(class path resource[yourbatman-test.txt])都处于命令行属性源(commandLineArgs)的上面了。

2.6.x版本属性源顺序:
在这里插入图片描述
2.7.0版本属性源顺序:
在这里插入图片描述
按照截图这个现象,不同版本咱的输出结果应该不一样才对,为何却是相同的呢。在Spring Boot 2.6.x版本里明明commandLineArgs属性源的优先级更高,为什么不是输出YourBatman_CL18_CL呢?难道是新版本Spring Boot有bug?
在这里插入图片描述
淡定,这么明显和严重的问题,拍脑袋想也不应该怀疑Spring Boot嘛。

其实,这里是笔者故意挖的一个坑,哈哈。细心的同学可能从上面的截图里已经发现了端倪,在这里:
在这里插入图片描述
问题出现在命令行参数里optionArgsnonOptionArgs的区别:

  • optionArgs:无key参数集,使用ArrayLisr存储
  • nonOptionArgs:有key参数集,使用HashMap存储

言外之意,就是写命令行参数时写错了呗,只需轻轻的修改一下:

@SpringBootTest(properties = {"name=YourBatman", "age=18"}, args = {"--name=YourBatman_CL", "--age=18_CL"})

哟西,原来是“忘记”写--了。这样子修改后,commandLineArgs属性源的情况如下:
在这里插入图片描述
在不同版本下再次运行,结果终于正确了。

Spring Boot 2.6.x版本,运行结果:

YourBatman_CL
18_CL

在Spring Boot 2.7.0版本,运行结果:

YourBatman
18

使用java -jar启动时,命令行参数相信你肯定不会忘记写上--,在Spring Boot测试时也一样。其实呀,@SpringBootTest的注释也提示到了我们应该如何使用:
在这里插入图片描述
Tips:关于命令行属性源CommandLinePropertySource的原理、optionArgs和nonOptionArgs的根本区别,在我公号里有解释,对这块技术原理有追求的同学可去看看。

✌Flyway模块化管理

2021年10月Flyway 8.0发布了,提供了对多个数据库的支持,并且对不同数据库的支持进行了模块化划分:

  • flyway-firebird:支持管理firebird数据库
  • flyway-mysql:支持管理mysql数据库
  • flyway-sqlserver:支持管理sqlserver数据库

这样子根据DB的不同,按需添加即可。Spring Boot 2.7.0版本开始内置管理上了这些模块依赖:
在这里插入图片描述而在此之前的Spring Boot版本只管理org.flywaydb:flyway-core核心模块,其它需要自己显示指定版本号。原因:flyway的模块并非一起发布的,比如flyway-firebird模块直到8.4版本才有,这之后才纳入统一版本管理更为合适。

✌H2升级到2.1

H2是最流行的内存数据库,可能没有之一,经典使用场景是用于单元测试。Spring Boot 2.7将H2升级到了2.1.x版本

<h2.version>2.1.212</h2.version>

在此之前的H2版本是:1.4.200

H2 2.x是向后不兼容的,并且修复了一些安全漏洞。这里是官方的发布日志http://www.h2database.com/html/changelog.html和升级指南http://www.h2database.com/html/migration-to-v2.html

✌弃用OkHttp 3,拥抱OkHttp 4

okhttp3的第一个版本于2016年1月发布,迅速“走红”,大有干过老牌客户端Apache HttpClient的势头。2019年6月OkHttp 4发布,全部使用kotlin编写

OkHttp 4虽然全部使用kotlin编写,但和okhttp 3几乎完全兼容,包括二进制兼容(运行期没问题)、源代码兼容(编辑期、使用时没问题),甚至为了和3.X兼容,包名都仍然保持了okhttp3
在这里插入图片描述
Spring Boot 2.6.x的3.x版本:

<okhttp3.version>3.14.9</okhttp3.version>

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>${okhttp3.version}</version>
</dependency>

Spring Boot 2.7.0的4.x版本:

<okhttp.version>4.9.3</okhttp.version>

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp-bom</artifactId>
    <version>${okhttp.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

两个小细节:

  1. 2.7.0版本开始使用的bom方式管理,方便了许多;而之前需要将常用模块一个个独立注名
  2. 2.7.0版本使用的okhttp.version,不同于之前的okhttp3.version。看来放弃3这个版本号的决心还是杠杠的

OkHttp 3早在2020年就已宣布不再维护,这次Spring Boot 2.7.0终于将其升级到了OkHttp 4。值得注意的是:若你仍想用回OkHttp 3,仅需修改okhttp.version的值即可(不再是okhttp3.version了哦)

到OkHttp 4的官方升级指南:https://square.github.io/okhttp/changelogs/upgrading_to_okhttp_4

✌ExitCodeGenerator支持排序

Spring框架提供了强大排序功能,支持声明式的@Order注解以及编码式的Ordered接口方式。

ExitCodeGenerator是Spring Boot提供的用于生成exit code的小工具,线上环境应用可能因为一些异常而终止,我们需要及时找到原因,根据 exit code 来定位就是个很好的途径。Spring Boot提供的exit退出方法,就会使用到它:

public static int exit(ApplicationContext context, ExitCodeGenerator... exitCodeGenerators) {
	int exitCode = 0;
	try {
		ExitCodeGenerators generators = new ExitCodeGenerators();
		// 从Spring容器里拿到所有的ExitCodeGenerator实例
		Collection<ExitCodeGenerator> beans = context.getBeansOfType(ExitCodeGenerator.class).values();
		generators.addAll(exitCodeGenerators); // 将方法传进来的添加进来
		generators.addAll(beans); // 将容器内的添加进来
		exitCode = generators.getExitCode(); // 拿到最终的退出码
		...
	}
	...
	return exitCode;
}

addAll底层调用的add方法,Spring Boot 2.7.0在add的时候支持了排序。如下对比图:
在这里插入图片描述

✌移除2.5.x标记为弃用的类

按照Spring Boot的约定,标记为@Deprecated的类、方法在2个版本后会被直接删除。这也告诉我们,谨慎使用@Deprecated的组件,保持良好习惯。

✌GraphQL终于“转正”

GraphQL 是一种针对 Graph(图状数据)进行查询特别有优势的Query Language(查询语言)。GraphQL 最大的优势是查询图状数据。GraphQL 是 Facebook 发明的。
在这里插入图片描述
Spring for GraphQL项目是基于GraphQL Java的,之前我们需要自己来整合到Spring Boot,现在不用了,它正式“转正”,Spring官方为其制作了启动器。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-graphql</artifactId>
</dependency>

Tips:在此之前的也有启动器叫graphql-spring-boot-starter,是社区行为

另外,由于GraphQL与传输无关,所以若要通过API暴露出去,还需通信环境。Web(Http协议)、WebSocket(WebSocket协议)、WebFlux(HTTP, WebSocket)、RSocket(TCP, WebSocket)都行。

✌/actuator/info端点新增os信息

访问端点:http://localhost:8080/actuator/info,可以看到操作系统信息:

{
  "os": {
    "name": "Mac OS X",
    "version": "12.3.1",
    "arch": "aarch64"
  }
}

相关实心源码参见OsInfoContributor类,获取操作系统信息的方式蛮简单的:
在这里插入图片描述
注意:由于自Spring Boot 2.6.0后,只公开了health端点,因此你要看到我这类似的效果,需要加些配置,比如:

management.endpoints.web.exposure.include=health,info
management.info.os.enabled=true

spring-boot-starter-actuator依赖不能少,这应该不用多说

🍞总结

作为一名Javaer,JDK和Spring框架是基础,当然也是最重要的基石。他哥俩现在疯了似的,一年两发,这要跟下去,真的太难顶了。

不过话说回来,JDK的新版本稍微了解下就行,只需重点关注LTS版本即可。但对于工业级的Spring Boot框架,每个中型版本最好都重视一下下,紧跟步伐,否则可能积重难升,这包括年底即将发布的大版本Spring Boot 3.0

不少人疑惑IT行业为何高薪,除了费身体、费头发外,超快的技术更新换代带来的学习压力也是重要原因之一吧~

新版IDEA提供的Dependency Analyzer依赖分析功能,笔者认为不输Maven Helper。重点是前者是原生自带的(且还支持Gradle),后者还得额外安装插件,孰优孰劣高下立判。所以,我头也不回的卸载了Maven Helper,相忘于江湖。

赶紧升级到最新的IDEA 2022.1版本吧,一起体验它的依赖分析工具,以及something else new~

本专栏上下文

推荐阅读

在这里插入图片描述

我是方向盘(YourBatman):前25年不会写Hallo World、早已毕业的大龄程序员。高中时期《梦幻西游》骨灰玩家,网瘾失足、清考、延期毕业、房产中介、保险销售、送外卖…是我不可抹灭的黑标签

  • 🎓2013.07 清考、毕业答辩3次未通过、延期毕业
  • 🏷2013.08-2014.07 宁夏中介公司卖二手房1年,毕业后第1份工作
  • ️️🏷2014.07-2015.05 荆州/武汉,泰康人寿卖保险3月、饿了么送外卖2月,还有炸鸡排、直销等第2345份工作
  • 🏷2015.08 开始从事Java开发,闯过外包,呆过大厂!擅长抽象思维,任基础架构团队负责人
  • 🏷2021.08 因“双减政策”失业!历经9面,终获美团外卖L8的offer
  • 🙅🏻‍♀️Java架构师、Spring开源贡献者、CSDN博客之星年度Top 10、领域建模专家、写作大赛1/2届评委
  • 📚高质量代码、规范践行者;DDD领域驱动深度实践;即将出版书籍《Spring奇淫巧技》

在这里插入图片描述

序号专栏名称简介
01【方向盘】-程序人生程序人生,人生程序
02【方向盘】-资讯/新特性IDEA、JDK、Spring技术栈…新特性
03【方向盘】-IntelliJ IDEA熟练使用IDEA就相当拥有物理外挂,助你高效编码
04【方向盘】-Bean Validation熟练掌握数据校验,减少90%的垃圾代码
05【方向盘】-日期时间帮你解决JDK Date、JSR 310日期/其实 的一切问题
06【方向盘】-Spring类型转换Spring类型转换-框架设计的基石
07【方向盘】-Spring staticstatic关键字在Spring里的应用
08【方向盘】-Cors跨域关于跨域请求问题,本专栏足矣
09【方向盘】-JacksonAlmost Maybe是最好的Jackson专栏
10【方向盘】-Spring配置类专讲@Configuration配置类,你懂的
11【方向盘】-Spring技术栈暂无所属小分类的,Spring技术栈大分类
12【方向盘】-JDK暂无所属小分类的,JDK技术栈大分类
13【方向盘】-ServletServlet规范、Web相关内容专题
14【方向盘】-Java EE从Java EE到Jakarta EE,30年弹指一挥间
15【方向盘】-工具/提效开发工具、软件工具,目标是提效
16【方向盘】-Spring技术栈新特性 Spring Framework、Spring Boot、Spring Cloud、Spring其它技术
99源代码库大多数专栏均配有源代码,都在这里
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐