Spring Batch 6.1.0-M2(2026-09-24,已上 Maven Central)把 6.1 线里多数「对读者有增量」的变更集中落地:Mongo job repository 可配 collectionPrefix,AsyncItemProcessor / AsyncItemWriter / ChunkTaskExecutorItemWriter 迁入 spring-batch-core,Avro 反射路径强制受信类。相对稳定线 6.0.x 这是小版本试水;相对同线的 6.1.0-M1(发行说明几乎只有修错与依赖抬到 *-M1),功能增量主要就在本里程碑。它仍是 milestone,未 GA,生产勿当稳定基线;试跑请对齐 Framework 7.1.0-M2 与 Data 2026.1.0-M2 列车。

适用边界先写清

稳定文档仍指向 Batch 6.0.x(撰写时提示最新稳定约 6.0.5)。本文只谈两件事:一是 6.1.0-M2 相对 6.0 的实质差,二是相对 6.1.0-M1 的功能落点。官方博文标题即 Spring Batch 6.1.0-M2 is out!,作者 Mahmoud Ben Hassine,日期 2026-09-24;GitHub v6.1.0-M2 发行说明与博文列点高度一致,可交叉核对。

M1 与 M2 不要混成「6.1 一整包都在 M1」。Mongo 集合前缀、异步 API 迁 core、RepositoryItemWriter flush、资源 location pattern、staged DSL、Derby 弃用等,均出现在 M2 的发行说明、博文,以及同标签下的 whatsnew 文档。站内已发 Data 2026.1.0-M2、Cloud Paddington、Boot 4.2.0-M2 专文,本文不展开那些产品细节,只保留 Batch 自身与依赖对齐数字。

还有一处容易踩坑:在线 6.1-SNAPSHOT whatsnew 另列「JDBC DAO 迁到 JdbcClient」。对照 v6.1.0-M2 标签源码,JdbcJobInstanceDao 等仍走 getJdbcTemplate(),该项不能算 M2 已交付。后文省略展开;是否进入后续 RC / GA,以届时发行说明为准。

依赖对齐:以 M2 博文与发行说明为准

组件M2 对齐版本
Spring Framework7.1.0-M2
Spring Integration7.2.0-M2
Spring Data2026.1.0-M2
Spring LDAP4.2.0-M1(博文数字;线级 whatsnew 写作「4.1」,试跑锁版本时以发行说明 / BOM 为准)
Spring AMQP4.2.0-M2
Spring Kafka4.2.0-M2
Micrometer1.18.0-M2

spring-batch-infrastructure 在 M2 使用 Apache Avro 1.12.2。Avro 侧的安全策略变化,会直接打到 AvroItemReader / AvroItemWriter,见下文破坏性说明。Data 列车号是 2026.1.0-M2,具体模块坐标在 BOM 里会落到如 spring-data-commons 4.2.0-M2 等,不必在应用里手写一长串,除非你脱离 BOM 管理。

Mongo job repository:collectionPrefix

JDBC 仓库早有 table prefix;Mongo 侧在 6.1 补上对等能力。@EnableMongoJobRepository(collectionPrefix = "MY_APP_") 给元数据集合加前缀,同一 Mongo 库可挂多个应用,也可按环境隔离集合命名。默认前缀仍是 BATCH_,存量应用不改注解则集合名不变,迁移成本可控。

@EnableBatchProcessing
@EnableMongoJobRepository(collectionPrefix = "MY_APP_")
class MyJobConfiguration {
    // job definition omitted
}

M2 发行说明另有 #5508:Mongo JobRepository 可与任意 PlatformTransactionManager 搭配。多数据源、或事务管理器并非「Mongo 默认那套」时,值得单独回归;配置细节以官方文档 Changing the Collection Prefix 与发行说明为准。

异步处理与本地分块:迁入 spring-batch-core

AsyncItemProcessor、AsyncItemWriter、ChunkTaskExecutorItemWriter(本地分块常用)原先住在 spring-batch-integration。官方说明很直接:它们只依赖 TaskExecutor,并不依赖 Spring Integration 消息通道,继续放在 integration 模块只会逼业务为「本地异步」拉上一棵额外依赖树。

自 M2 起,正式类型落在 org.springframework.batch.core.step.item(spring-batch-core)。旧包路径保留为弃用子类,现有 classpath 一般还能跑;新代码改 import,并可评估是否拿掉仅为此引入的 spring-batch-integration。

// before
import org.springframework.batch.integration.async.AsyncItemProcessor;
import org.springframework.batch.integration.async.AsyncItemWriter;
import org.springframework.batch.integration.chunk.ChunkTaskExecutorItemWriter;

// after
import org.springframework.batch.core.step.item.AsyncItemProcessor;
import org.springframework.batch.core.step.item.AsyncItemWriter;
import org.springframework.batch.core.step.item.ChunkTaskExecutorItemWriter;

文档强调这是 packaging 变更,不引入行为变化。真正的「远程分块 / 远程分区」仍在 integration 与相关通道模型里,不要把本次迁移动作理解成远程模型也搬进了 core。

RepositoryItemWriter:chunk 后可 flush

写 Spring Data repository 时,chunk 边界与持久化上下文 / 一阶缓存是否对齐,常常要靠额外 flush。M2 给了两条路:

  1. 仓库已有「保存并 flush」的方法(典型如 JpaRepository#saveAllAndFlush),setMethodName("saveAllAndFlush") 即可。初始化时会识别该方法吃 Iterable(整 chunk 调一次)还是单条(逐条调)。
  2. 保存与 flush 分离时,子类覆写新的 flush();repository 字段改为 protected,子类可直接访问。

JPA 批写、需要在 chunk 提交前看见库内状态的测试或后续 reader,会更省事。仍用旧 setRepository setter 的代码会看到弃用提示,官方倾向构造器注入 repository,计划 7.0 再清理。

资源 location pattern

MultiResourceItemReaderBuilder 现在直接接受 pattern 字符串,内部用 PathMatchingResourcePatternResolver 解析,业务配置里少写一段「先解析 Resource[] 再注入」的样板:

return new MultiResourceItemReaderBuilder<Foo>()
    .delegate(flatFileItemReader())
    .resources("classpath:data/input/file-*.txt")
    .build();

file:、classpath:、classpath*: 以及 Ant 风格通配均可。同期新增 ResourcesItemReaderBuilder,给 ResourcesItemReader 同样的 pattern 能力。文件名滚动、按日落地的多文件输入,配置会短一截。

Avro 反射路径:必须显式信任(破坏性)

这是本里程碑里最「会突然红」的点。Apache Avro 1.12.2 拒绝未列入受信集合的类走反射(反)序列化;AvroItemReader / AvroItemWriter 在 SpecificRecord 或普通 Java item 类型上会命中。GenericRecord 不受影响。未配置时,作业在运行期抛 SecurityException,而不是编译期友好提示。

-Dorg.apache.avro.SERIALIZABLE_PACKAGES=com.example.domain

也可用 org.apache.avro.SERIALIZABLE_CLASSES,或程序化配置 org.apache.avro.util.ClassSecurityValidator。字段图上嵌套的自定义类型要一并信任,只放顶层包名不够时按 Javadoc 补全。从 6.0.x 抬到 M2(或同 Avro 基线)时,Avro 作业应列入回归清单第一排。

staged DSL:互斥配置改为编译期失败

若干 builder 过去允许把互斥策略写在同一条链上,拖到 build() 才 IllegalStateException:

  • FlatFileItemReaderBuilder#targetType 与 #fieldSetMapper
  • FlatFileItemWriterBuilder 的 delimited / formatted
  • JdbcBatchItemWriterBuilder 的 columnMapped / beanMapped

现改为 staged DSL:调用其中一侧后,返回的 stage 类型不再暴露冲突方法,非法组合在编译期就被拦下。tokenizer / line mapping(delimited()、fixedLength()、lineTokenizer())与 targetType / fieldSetMapper 的先后顺序仍然灵活。

破坏面要说清楚:这些方法的返回类型从「builder 自身」变成「专用 stage」,属源码与二进制破坏。纯流畅链式调用通常只需重编译;把中间结果存成 builder 具体类型、或依赖捕获非法组合异常做分支的代码,需要改写。官方指向 issue #4888。

弃用与其它值得扫一眼的增量

Derby:DatabaseType.DERBY、DerbyPagingQueryProvider 与 Derby DDL 脚本弃用,计划在 7.0.0 移除。背景是 Apache Derby 项目已退役,还在用内嵌 Derby 跑 Batch 元数据的团队应开始迁 H2 / 正式库。

默认 conversion service 改为基于 Framework 的 DefaultFormattingConversionService,经 ConversionServiceFactory#createConversionService() 暴露。job 参数既有格式(如 java.util.Date 的 ISO_INSTANT,以及各 java.time 类型的标准 ISO)保持,顺带获得 Framework 自带的更广 converter 集合。旧的手写 DateToStringConverter 等标记弃用。

便捷 getter 也在收缩:StepExecution#getJobExecutionId() / getJobParameters() 建议改走 getJobExecution();JobExecution#getJobInstanceId() 改走 getJobInstance()。若干 getJobInstanceCount / getStepExecutionCount 类 API 改名为 count* 语义,并说明「无法在 DAO 层可靠区分未知 job 名与零次执行」,校验应上提到带 job registry 的 operator 层。计划均在 7.0 移除。

其余偏体验的增量:DatabaseType 提供 schema 创建 / 删除脚本的 classpath 位置,减少手写路径笔误;会把状态写入 ExecutionContext 的 reader/writer builder 在 saveState=true 时可不强制 name()(默认短类名,声明为 bean 时用 bean 名),同 step 多实例时仍建议显式命名;BatchConstants 集中框架常量。完整列表看 GitHub v6.1.0-M2 与 reference whatsnew。

试跑时怎么排优先级

  1. 锁版本到 6.1.0-M2,依赖列车与上表一致,避免「Batch M2 + Framework 稳定 7.0」混搭。
  2. 有 Avro 反射读写的作业:先配 SERIALIZABLE_PACKAGES / CLASSES,再谈业务断言。
  3. 本地异步 / 本地分块:改 import,评估能否去掉 integration 依赖。
  4. Mongo 多应用共库:确认 collectionPrefix 与运维命名约定。
  5. 编译:盯 staged DSL 与 builder 中间变量类型。
  6. Derby 元数据:列入迁出计划,不必等 7.0 再被动替换。

配置若走 @EnableBatchProcessing、@EnableJdbcJobRepository、JdbcJobRepositoryFactoryBean 等官方装配,一般碰不到底层 DAO 构造细节;自管 Jdbc*Dao 的代码请持续盯后续里程碑是否引入 JdbcClient 构造器要求。反馈走 GitHub Issues / Discussions;RC / GA 前数字与弃用列表仍可能微调,以官方为准。

— 感谢阅读 —

一起交流

分享你的思考,让讨论更进一步。