我有我的批注处理器:
public class MyAnnotationProcessor extends AbstractProcessor {
...
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// Here I deal with the annotated element
...
// use JavaPoet to generate Java source file
TypeSpec generatedClazz = generate_code();
JavaFile javaFile = JavaFile.builder("com.my.foo", generatedClazz).build();
javaFile.writeTo(filer);
}
}
在处理上述process
回调中的带注释元素之后,我使用JavaPoet生成java源代码并为代码创建Java文件。在构建我的项目时,除了缺省情况下生成的java源代码文件被放入build/generated/sources/myApp/com/my/foo
之外,其他一切都可以正常工作。如何使生成的Java文件位于项目的源代码位置src/main/java/com/my/foo
?
我的gradle版本:
plugins {
id 'java'
}
group 'com.my.app'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testImplementation 'junit:junit:4.12'
implementation 'com.squareup:javapoet:1.11.1'
implementation 'com.google.guava:guava:28.1-jre'
}
发布于 2019-10-11 05:11:16
坏消息是:批注处理器不能做到这一点--其循环工作方式的本质意味着,在“实际”源代码所在的同一目录中生成源代码是没有意义的,因为这些生成的源代码将在批注处理器下次运行时被视为输入。
好消息是: JavaPoet不知道如何实际调用它,所以您可以只编写一个简单的main()来执行代码生成,并要求您的集成开发环境在构建时调用它,或者将其附加到gradle构建。如果您计划在生成源代码后手动编辑它们,您可能不希望发生这种情况,因为您可能希望保留您的手动更改,而不是在每次构建时覆盖它们。
JavaFile.writeTo(...)
方法有几个重写,其中只有一个接受批注处理器Filer
。使用Filer
有一些优点--您可以很清楚地知道要在哪里编写类--但JavaFile.writeTo(File directory)
也意味着要以这种方式使用。您不需要向它传递您希望MyClass.java所在的实际文件,而只需要传递您想要写入的源目录。在您的例子中,这大概是javaFile.writeTo(new File("myProject/src/main/java"))
。
您可能仍然应该参数化如何调用这个main,以便它知道要使用什么输入,如何理解您现有的源代码,等等。另一方面,如果您的generate_code()
不需要来自同一项目的任何现有源代码来运行,这应该是非常简单的。
发布于 2019-12-06 00:45:27
不太确定gradle,但是使用maven,你可以使用maven编译器插件中的以下标签来定义生成的源代码目录。
<generatedSourcesDirectory>
${project.basedir}/src/main/java
</generatedSourcesDirectory>
有关完整的示例,请查看下面的链接。
https://www.thetechnojournals.com/2019/12/annotation-processor-to-generate-dto.html
https://stackoverflow.com/questions/58310822
复制相似问题