我编写了一个简单的 java 注释处理器,它生成一个 java 文件和一个资源文件。
我已经将注释处理器打包到一个 jar 文件中,我的 Maven 项目可以在Maven 生命周期的编译阶段加载它并处理注释。生成的代码按预期出现在target/ generated-sources/annotations中,生成的资源文件出现在target/classes中。
不过,我只想在测试期间使用生成的 java 文件和资源文件,因此我希望生成的文件分别出现在target/ generated-test-sources/test-annotations和target/test-classes中。简而言之,我需要在测试编译阶段而不是编译阶段进行注释处理。
更重要的是:注释处理器在生产代码上运行,但生成的文件随后包含在target\foo-test.jar中,而不是target\foo.jar 中。
我不知道如何使用 Maven 执行此操作,除非可能在流程测试资源阶段移动生成的文件,这看起来像是一个丑陋的黑客。
有什么建议么?
编辑:我尝试添加<scope>test</scope>对注释处理器的依赖关系,我可以看到处理器是在testCompile阶段创建的,但是处理器的process()方法没有被调用,并且没有任何反应。
编辑#1:注释处理器包含以下代码,用于在META-INF/services下写入 .java 文件和资源文件:
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
List<String> declarations = generateDeclarationsForAnnotation(roundEnv);
generateServiceImplFile(declarations);
generateResourceFile();
return true;
}
private void generateResourceFile() throws Exception {
JavaFileManager.Location location = StandardLocation.CLASS_OUTPUT;
FileObject file= processingEnv.getFiler().createResource(location,
"", "META-INF/services/x.y.z.FooService");
BufferedWriter writer = new BufferedWriter(file.openWriter());
... write resource file ...
}
private void generateServiceImplFile(List<String> declarations) throws Exception {
JavaFileObject file = processingEnv.getFiler().createSourceFile("x.y.z.FooServiceImpl");
BufferedWriter writer = new BufferedWriter(file.openWriter());
... write source code ...
}
Run Code Online (Sandbox Code Playgroud)
我目前在文件中声明依赖项pom.xml如下:
<!-- Dependency for the @Foo annotation -->
<dependency>
<groupId>x.y.z</groupId>
<artifactId>foo-annotations</artifactId>
<scope>compile</scope>
</dependency>
<!-- Dependency for the @Foo annotation processor -->
<dependency>
<groupId>x.y.z</groupId>
<artifactId>foo-annotations-processor</artifactId>
<scope>compile</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我使用的是 JDK 1.7,maven-compiler-plugin版本 3.1。注释处理器是通过其存在于类路径中而被调用的。我没有添加任何处理器插件等,或调整编译器插件等来使其工作。
编辑#2:我对以下内容进行了更改maven-compiler-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<executions>
<!-- Disable annotation processing for default compile execution -->
<execution>
<id>default-compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<proc>none</proc>
</configuration>
</execution>
<!-- Only annotation process in this execution, with generated code
going to generated-test-sources directory. -->
<execution>
<id>compile-with-annotations-processor</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<proc>only</proc>
<generatedSourcesDirectory>
${project.build.directory}/generated-test-sources/test-annotations
</generatedSourcesDirectory>
</configuration>
</execution>
</executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)
这会禁用default-compile执行的注释处理,并且compile-with-annotations-processing执行仅进行注释处理,将生成的源放入target\ generated-test-sources\test-annotations目录中。
当我运行它时,我在target/ generated-test-sources/test-annotations目录中看到生成的 java 文件,尽管资源文件仍然出现在target/classes目录中。我猜我可以通过更改generateResourceFile()使用方法StandardLocation.SOURCE_OUTPUT而不是 来解决这个问题StandardLocation.CLASS_OUTPUT。
此外,此修复无法优雅地处理多个注释处理器。我真的只希望在执行过程中禁用这个特定的注释处理器default-compile,并且在compile-with-annotations-processing执行过程中只启用该处理器(具有不同的源目录)。否则,如果我添加另一个(不相关的)注释处理器,它生成的代码将不会出现在预期的位置。
编辑#3:也许一个更简单的解决方案是允许编译器正常运行注释处理器,然后使用例如将生成的文件从target\ generated-sources移动到target\ generated-test-sources 。maven-antrun-plugin
编辑#4:我想我已经解决了这个问题,使用maven-antrun-plugin上面提到的:
maven-antrun-plugin将文件从target/ generated-sources/annotations移动到target/ generated-test-sources/test-annotations,并从target/classes/META-INF/services移动到target/test-classes/META-INF/services,期间编译阶段。build-helper-maven-plugin将target/ generated-test-sources添加到generate-test-sources阶段。我的foo.jar和foo-test.jar似乎构建正确:-)
编辑 #5:我发现了一个名为 的插件maven-processor-plugin,并将其配置为在生产代码的生成测试源阶段运行,并将输出目录设置为target/ generated-test-sources/annotations和target/test-类。奇迹般有效。所以现在根本就没有必要了maven_antrun_plugin。
我发现了一个名为 的插件maven-processor-plugin,并将其配置为generate-test-sources在生产代码的阶段运行,并将输出目录设置为target/ generated-test-sources/annotations和target/test-classes。奇迹般有效。所以现在根本就没有必要了maven_antrun_plugin。
我提出的另一个解决方案(因为有时使用可能maven-compiler-plugin比使用更好maven-processor-plugin)是在阶段使用注释处理器生成代码compile,以便代码最终位于通常的target/ generated-sources/annotations目录中。同一模块中的测试代码可以访问此位置,并且测试运行良好。然后我将其配置为从.jarmaven-jar-plugin中排除生成的代码,并将生成的代码包含在名为-test-libs.jar的新工件中。然后其他模块添加对-test-libs 的测试依赖项。artifactIdartifactIdartifactId