6.3 Maven 与 Kotlin:多语言协同构建


文档摘要

6.3 Maven 与 Kotlin:多语言协同构建 本节摘要:Kotlin 与 Java 混编工程的关键配置是 kotlin-maven-plugin 的编译顺序(先 Kotlin 后 Java),版本纪律要求编译器与标准库对齐(由 kotlin-bom 仲裁),增量编译开关与源码目录声明决定构建体验。本节给出可直接套用的双模块配置与三类高频翻车点的处置。 为什么规则引擎改用 Kotlin 写 risk-engine 的规则解析模块重写选了 Kotlin:密封类与模式匹配让规则分支的表达力上一个台阶,空安全把一类运行期异常变成编译期报错。但工程现实是:其他模块仍是 Java,团队不可能一夜切换。于是问题变成:同一个 Maven 工程里,两种语言怎么共存共编?

6.3 Maven 与 Kotlin:多语言协同构建

本节摘要:Kotlin 与 Java 混编工程的关键配置是 kotlin-maven-plugin 的编译顺序(先 Kotlin 后 Java),版本纪律要求编译器与标准库对齐(由 kotlin-bom 仲裁),增量编译开关与源码目录声明决定构建体验。本节给出可直接套用的双模块配置与三类高频翻车点的处置。

为什么规则引擎改用 Kotlin 写

risk-engine 的规则解析模块重写选了 Kotlin:密封类与模式匹配让规则分支的表达力上一个台阶,空安全把一类运行期异常变成编译期报错。但工程现实是:其他模块仍是 Java,团队不可能一夜切换。于是问题变成:同一个 Maven 工程里,两种语言怎么共存共编

混编的核心矛盾只有一个:编译顺序。Java 编译器不认识 Kotlin 源文件,Kotlin 编译器却能先编译自己并把产物给 Java 用。所以标准编排在 Maven 里是"先 Kotlin 后 Java"——kotlin 插件绑到更早的阶段,Java 编译器随后把 Kotlin 的产物当普通 class 文件引用。

标准配置:先 Kotlin 后 Java

<build> <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory> <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory> <plugins> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <executions> <!-- 编排核心:Kotlin 编译挂到 compile 与 test-compile 的前面 --> <execution> <id>compile</id> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile</id> <goals> <goal>test-compile</goal> </goals> </execution> </executions> <configuration> <!-- 增量编译:开发期反馈速度的关键开关 --> <args> <arg>-Xincremental</arg> </args> </configuration> </plugin> </plugins> </build>

依赖侧只需标准库,版本交给 BOM:

<dependencyManagement> <dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-bom</artifactId> <version>1.9.10</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib</artifactId> <!-- 版本由 BOM 裁决 不写字面量 --> </dependency> </dependencies>

三类高频翻车点

翻车一:编译顺序配错。 症状是 Java 代码引用 Kotlin 类时编译器报"找不到符号"。诊断看构建日志里两个编译器的执行顺序——kotlin 的 compile goal 必须出现在 maven-compiler-plugin 之前。多数成因是 executions 的编排被后来者覆盖,或从别的项目抄配置时丢了 execution。处置武器仍是老三样:有效 POM 看最终编排,日志看实际顺序,最小工程复现验证。

翻车二:编译器与标准库版本错位。 kotlin-stdlib 1.8 的 API 配 1.6 的编译器,编译期报元数据版本不兼容;反过来用新编译器编旧库,警告刷屏。版本对齐纪律:kotlin.version 属性(管插件即编译器)与 kotlin-bom 版本(管标准库与协程等家族)必须同步走,升级时一起动。这条纪律与第 3.3 节"版本只有一个家"一脉相承,只是 Kotlin 的坑在于版本散落在两处,务必收敛到一个属性。

翻车三:协程依赖的传递面失控。 Kotlin 工程引入协程库后,传递树里多出几级 Kotlin 家族构件,与 Java 侧引入的其他 Kotlin 系库(例如某客户端库自带 Kotlin 支持)相遇时,版本调解照第 3 章规则执行。处置是熟悉的配方:平台 BOM 钉住 Kotlin 家族版本,verbose 树核对调解结果。多语言没有发明新的依赖规则,只是把战场从 Java 族扩大到了 Kotlin 族。

工程组织的两种模式

模式 结构 适用 代价
单模块混编 一个模块里两种源码目录 试点期 小规模渗透 配置耦合 测试覆盖复杂
分模块分语言 rule 模块纯 Kotlin web 模块纯 Java 稳定演进 模块边界要清晰

risk-engine 的演进路径是先单模块试点(一个服务里两页 Kotlin 文件验证表达力收益),三个月后拆出独立的 Kotlin 模块。建议超过两成的代码是 Kotlin 时就走分模块——单模块混编的编译编排、测试配置、IDE 行为都要同时伺候两种语言,分模块让每种语言待在自己舒适的配置里,模块边界(第 4.1 节的原则)天然就是语言边界。

⚠️ 常见坑:只加 kotlin 插件不加标准库依赖(或反之)。插件管编译,标准库管运行期符号,两者缺一:前者让构建当场失败,后者让运行期才报类找不到。配置检查清单两项必须成对出现。

💡 关键直觉:判断一个混编工程配置是否健康的速查法——看 kotlin.version 这个属性在全部 POM 里出现了几处。一处(父 POM 的 properties)是健康,两处以上就开始有错位风险,散落各处则是第 3 章丛林裁决的多语言复刻。

战报小结

  • 编译顺序是混编的命门:先 Kotlin 后 Java,executions 编排决定,日志验证顺序;
  • 版本对齐一条纪律:编译器属性与标准库 BOM 同步升,kotlin.version 全工程只出现一次;
  • 依赖规则没有语言特权:Kotlin 家族构件照第 3 章规则调解,平台 BOM 钉版本;
  • 两成阈值走分模块:单模块混编是试点形态,分模块让语言边界与模块边界重合;
  • 插件与标准库成对出现:一个管编译一个管运行期,缺谁都会炸,只是炸的时机不同。

语言协同就绪。下一节进入交付形态的性能极点:GraalVM 原生镜像——把 JVM 世界编译成原生二进制的完整战役与排障路径。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U