Java11迁移中如何配置Maven生成/复制module-info.java到target目录
Java 11 模块化项目搭配注解处理器的Maven配置方案
核心问题本质是Maven默认编译流程下,注解处理器执行、普通源码编译、module-info编译三者的执行顺序错位,会出现生成类未被模块识别、module-info未被编译到输出目录的问题,按以下配置即可解决:
1. 基础配置:拆分maven-compiler-plugin编译阶段
使用3.11.0及以上版本的maven-compiler-plugin,把编译拆成两步:第一步先编译所有普通源码、执行全部注解处理器生成代码,跳过module-info编译;第二步单独编译module-info到输出目录,此时所有生成类已经存在,不会报类找不到的错误。
配置示例如下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <release>11</release> <!-- 首轮编译排除module-info --> <excludes> <exclude>**/module-info.java</exclude> </excludes> <annotationProcessorPaths> <!-- 替换为项目实际使用的所有注解处理器依赖,不要依赖传递引入 --> <!-- 示例: <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> </path> --> </annotationProcessorPaths> </configuration> <executions> <!-- 次轮单独编译module-info --> <execution> <id>compile-module-info</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> <configuration> <excludes> <exclude>none</exclude> </excludes> <includes> <include>**/module-info.java</include> </includes> </configuration> </execution> </executions> </plugin>
2. 特殊场景:module-info由注解处理器生成的额外配置
如果你的module-info.java不是手写在src/main/java下,而是由注解处理器生成到target/generated-sources目录下,需要额外引入build-helper-maven-plugin把生成目录注册为源码根目录,否则编译器无法识别到生成的module-info文件:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>3.4.0</version> <executions> <execution> <id>register-generated-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <!-- 替换为你的注解处理器生成源码的实际目录 --> <source>${project.build.directory}/generated-sources/annotations</source> </sources> </configuration> </execution> </executions> </plugin>
配置校验和注意事项
- 所有注解处理器必须显式配置在
annotationProcessorPaths标签内,不要依赖classpath自动发现,Java 11模块化场景下自动发现机制大概率失效。 - 手写module-info时,记得把注解处理器生成的、需要对外暴露的包加到
exports声明里,如果生成类需要反射访问模块内的包,对应包要加opens声明给依赖的模块。 - 配置完成后执行
mvn clean compile,检查target/classes根目录下是否存在module-info.class,同时所有注解处理器生成的类都在对应包路径下,执行java --describe-module 你的模块名 -p target/classes能正常输出模块信息就代表配置生效。 - 不要把手写的module-info.java放到生成源码目录下,执行clean构建时会被生成的文件覆盖。
内容的提问来源于stack exchange,提问作者greg1337
相关产品推荐
相关产品推荐

