告别手动升级!Spring Boot 4 迁移工具节省95%时间!

63 阅读5分钟

Spring Boot 4 来了,很多团队开始焦虑:现有项目如何升级,升级要多久?

上周,我用 excel-spring-boot-starter 项目测试了一下迁移工具。

这是个 Pig 生态的 Spring Boot Starter,基于 EasyExcel** 封装 Excel 导出功能。20 个 Java 类,10 个测试类。

因为确实这次 SpringBoot4 的依赖包变更改动较多,手动迁移的话,查文档、改代码、调测试...保守估计 1-2 天。但用工具,10 分钟搞定

OpenRewrite** 和 Arconia 这两个工具,真的能把 Spring Boot 升级从"噩梦"变成"自动化"。

Spring Boot 4 升级的三大难题

难题 1:依赖地狱

Spring Boot 4 不是简单的版本号跳跃,它带来了整个技术栈的升级:

  • Spring Boot 模块化:依赖 artifactId 大量变更
  • Spring Framework 7:核心框架大版本升级
  • JUnit 6:测试框架从 5 升级到 6
  • Testcontainers 2:容器测试工具大版本跳跃
  • Jackson 3**:JSON 序列化库的破坏性升级

每个依赖都可能带来 API 变化,手动一个个查文档、改代码,光想想就头疼。

难题 2:API 破坏性变更

Spring Boot 4 有大量不兼容的 API 变更:

  • 配置属性调整(如 spring.jackson.datetime.* 移到了新位置)
  • 废弃 API 替换(字段注入改构造器注入)
  • 类型重命名(ObjectMapper → JsonMapper

这些改动散布在几百个文件里,手动查找替换?容易漏,还容易改错。

而且手动操作还有隐患:遗漏、改错、引入新 Bug。每次发版都提心吊胆。

对于初中级开发者来说,最头疼的是:不知道改哪些,也不知道改对了没有

OpenRewrite:自动化迁移的"黑科技"

什么是 OpenRewrite?

OpenRewrite 是个开源的自动化重构工具。核心就一点:理解你的代码,而不是简单的文本替换

传统的查找替换:

# 这样改很危险
find . -name "*.java" -exec sed -i 's/javax./jakarta./g' {} ;

可能会把注释、字符串里的 javax. 也改了,甚至破坏代码。

OpenRewrite 的做法:

  1. 把代码解析成 AST(抽象语法树)
  2. 理解代码的语义和结构
  3. 精确地修改需要改的地方
  4. 生成更新后的代码

举个例子,它能识别出:

  • 这是一个 import 语句 → 需要替换
  • 这是字符串中的文本 → 不需要替换
  • 这是注释中的说明 → 不需要替换

这就是为什么它能做到 90-95% 的自动化覆盖率。

Recipe 机制:预定义的迁移规则

OpenRewrite 的核心是 Recipe(配方)机制。

想象一下,升级 Spring Boot 就像做菜:

  • 手动升级 = 自己研究怎么切菜、炒菜、调味
  • OpenRewrite = 用现成的菜谱,一步步照着做

Spring Boot 4 的迁移 Recipe 已经内置了:

  • Spring Framework 7 升级规则
  • JUnit 5 → 6 迁移规则
  • javax → jakarta 替换规则
  • 配置属性迁移规则
  • 最佳实践应用(如字段注入 → 构造器注入)

你不需要知道每个细节,工具已经帮你总结好了

工作流程

整个流程是这样的:

源代码
  ↓
解析为 AST(理解代码结构)
  ↓
应用 Recipes(执行迁移规则)
  ↓
生成更新后的代码
  ↓
你审查变更(git diff)

工具负责 90-95% 的脏活累活,你只需要:

  1. 配置插件
  2. 执行命令
  3. 审查变更
  4. 处理剩余的 5-10%

快速迁移 Arconia CLI**(最快)

Arconia 是基于 OpenRewrite 的命令行工具,专门为 Spring Boot 迁移优化。

brew 安装

brew install arconia-io/tap/arconia-cli

Windows 用户

# 直接从 GitHub 下载最新 release
# https://github.com/arconia-io/arconia-cli/releases
# 下载 arconia-cli-windows-amd64.exe
# 然后在命令行运行
arconia-cli-windows-amd64.exe update spring-boot --to-version 4.0

使用

# 一键迁移到 Spring Boot 4.0
arconia update spring-boot --to-version 4.0

就这么简单。

工具会自动:

  • 扫描项目
  • 识别当前 Spring Boot 版本
  • 应用所有必要的 recipes
  • 更新代码和配置

优势

  • 零配置,开箱即用
  • 最快速,适合快速验证

从代码看工具威力

案例 1:构造器注入替代字段注入

Spring Boot 4 推荐使用构造器注入,而不是字段注入。这是一个最佳实践,但手动改很麻烦。

迁移前(Spring Boot 2.x/3.x):

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        return ResponseEntity.ok(userService.findById(id));
    }
}

迁移后(Spring Boot 4):

@RestController
@RequestMapping("/api/users")
publicclass UserController {

    privatefinal UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public ResponseEntity<UsergetUser(@PathVariable Long id) {
        return ResponseEntity.ok(userService.findById(id));
    }
}

变化解读

  1. 移除了 @Autowired 注解
  2. 字段改为 final(不可变,更安全)
  3. 添加了构造器注入

为什么这样更好

  • 依赖关系更清晰(一眼看出这个类需要什么)
  • 测试更容易(可以直接 new 对象,不需要 Spring 容器)
  • 不可变性(final 字段不会被意外修改)

OpenRewrite 会自动帮你完成这个转换,整个项目几百个类,全部自动处理。

案例 2:JUnit 测试迁移

JUnit 从 5 升级到 6,API 有变化。

迁移前(JUnit 5):

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class UserServiceTest {

    @Test
    public void testFindUser() {
        // 测试代码
    }
}

迁移后(JUnit 6):

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@SpringBootTest
class UserServiceTest {  // public → 默认访问权限

    @Test
    void testFindUser() {  // public → 默认访问权限
        // 测试代码
    }
}

变化解读

  • JUnit 6 的测试类和方法不再需要 public
  • 包路径可能有调整
  • 部分断言方法的参数顺序调整

这些细节,手动改很容易漏。OpenRewrite 自动搞定。

迁移 excel-spring-boot-starter

我实际测试了 excel-spring-boot-starter 项目的迁移,这是一个 Pig 生态的 Spring Boot Starter 项目,基于 EasyExcel 和 FastExcel 封装了 Excel 导出功能。

测试过程

# 克隆项目
git clone git@github.com:pig-mesh/excel-spring-boot-starter.git
cd excel-spring-boot-starter

# 一键迁移
arconia update spring-boot --to-version 4.0

项目规模

  • 约 20 个 Java 类(Starter 项目,规模较小)
  • 10 个测试类
  • 核心功能:Excel 导出自动配置、注解处理、模板引擎

自动处理的内容

  • Spring Boot 依赖升级(3.x → 4.0),主要是依赖 artifactId 的变更
  • 自动配置类的构造器注入改造
  • 测试类的 JUnit 版本升级
  • 配置属性的命名空间调整

这些artifactId变更,没有自动化工具,根本不知道如何迁移这些artifactId变更,没有自动化工具,根本不知道如何迁移

这个案例说明,即使是小型 Starter 项目,自动化工具也能大幅提升效率。对于更大的业务项目,效果会更明显。

避坑指南

  • 2.x → 3.x → 4.0(分步升级)
  • 每次大版本跳跃都有破坏性变更
  • 分步升级更容易定位问题
  • OpenRewrite 的 recipes 也是按版本设计的