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策略,可参照笔者之前写的文章,有详细解释。
所属专栏
相关下载
版本约定
?正文
从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 注解,有了它这下就好区分了,语义更加清晰。
@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_CL和18_CL呢?难道是新版本Spring Boot有bug? 淡定,这么明显和严重的问题,拍脑袋想也不应该怀疑Spring Boot嘛。
其实,这里是笔者故意挖的一个坑,哈哈。细心的同学可能从上面的截图里已经发现了端倪,在这里: 问题出现在命令行参数里optionArgs和nonOptionArgs的区别:
- 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>
两个小细节:
- 2.7.0版本开始使用的
bom 方式管理,方便了许多;而之前需要将常用模块一个个独立注名 - 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();
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奇淫巧技》
|