注解处理器在编译期读取源码结构、生成代码、报出诊断。这篇真实写一个只有几十行的处理器,逐项验证它的轮次、生成文件、诊断位置,以及处理器被发现的几种方式。
javac rc = 0
[processor] 结束,本处理器共生成 [PersonBuilder]
Note: 为 Person 生成 PersonBuilder(2 个字段)
-s 目录里的生成文件: ['gen1/demo/PersonBuilder.java'] ;-d 里的 class: ['Main.class', 'Person.class', 'PersonBuilder.class']
生成的 PersonBuilder.java:
package demo;
public class PersonBuilder {
private java.lang.String name;
public PersonBuilder name(java.lang.String v) { this.name = v; return this; }
private int age;
public PersonBuilder age(int v) { this.age = v; return this; }
public Person build() { return new Person(name, age); }
}
Ann/30
javap 看 Person.class 是否还带 @AutoBuilder(RetentionPolicy.SOURCE): False[processor] 第 1 轮:annotations=[AutoBuilder],根元素 [Person, Main],processingOver=false,errorRaised=false [processor] 第 2 轮:annotations=[],根元素 [PersonBuilder],processingOver=false,errorRaised=false [processor] 第 3 轮:annotations=[],根元素 [],processingOver=true,errorRaised=false [processor] 结束,本处理器共生成 [PersonBuilder] Note: 为 Person 生成 PersonBuilder(2 个字段)
正常:javac rc = 0
[processor] 结束,本处理器共生成 [PersonBuilder, EmptyBuilder]
Note: 为 Person 生成 PersonBuilder(2 个字段)
app/demo/Empty.java:1: warning: Empty 没有实例字段,生成的 Builder 是空的
package demo; import ap.AutoBuilder; @AutoBuilder public class Empty { public Empty() {} }
^
Note: 为 Empty 生成 EmptyBuilder(0 个字段)
1 warning
加 -Aap.fail=1:javac rc = 1
[processor] 结束,本处理器共生成 [PersonBuilder]
app/demo/Person.java:1: error: Person 被配置为失败(-Aap.fail)
package demo; import ap.AutoBuilder; @AutoBuilder public class Person { final String name; final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String toString() { return name + "/" + age; } }
^
Note: 为 Person 生成 PersonBuilder(2 个字段)
1 error
失败时 -d 下的 class 数: 0 ;生成的 PersonBuilder.java 在 -s 目录里: True
加 -Werror(处理器发了 WARNING):javac rc = 1 ; ['error: warnings found and -Werror specified'] classpath 上有 services 文件、什么选项都不加(JDK 21):rc=0,生成源文件 ['PersonBuilder.java'],class ['Main.class', 'Person.class', 'PersonBuilder.class']
[processor] 结束,本处理器共生成 [PersonBuilder]
Note: Annotation processing is enabled because one or more processors were found
on the class path. A future release of javac may disable annotation processing
unless at least one processor is specified by name (-processor), or a search
path is specified (--processor-path, --processor-module-path), or annotation
processing is enabled explicitly (-proc:only, -proc:full).
Use -Xlint:-options to suppress this message.
Use -proc:none to disable annotation processing.
Note: 为 Person 生成 PersonBuilder(2 个字段)
javac 输出: [' [processor] 结束,本处理器共生成 [PersonBuilder]', 'Note: Annotation processing is enabled because one or more processors were found', ' on the class path. A future release of javac may disable annotation processing']
加 -proc:none:rc=1,生成源文件 [],class ['Person.class']
app/demo/Main.java:1: error: cannot find symbol
package demo; public class Main { public static void main(String[] a) { System.out.println(" " + new PersonBuilder().name("Ann").age(30).build()); } }
^
symbol: class PersonBuilder
location: class Main
1 error
加 -proc:full:rc=0,生成源文件 ['PersonBuilder.java'],class ['Main.class', 'Person.class', 'PersonBuilder.class']
[processor] 结束,本处理器共生成 [PersonBuilder]
Note: 为 Person 生成 PersonBuilder(2 个字段)
javac 输出: [' [processor] 结束,本处理器共生成 [PersonBuilder]', 'Note: 为 Person 生成 PersonBuilder(2 个字段)']
-proc:only(只跑处理器,不生成 class):rc=0,生成源文件 ['PersonBuilder.java'],class []
[processor] 结束,本处理器共生成 [PersonBuilder]
Note: 为 Person 生成 PersonBuilder(2 个字段)
用 -processorpath 指定处理器、classpath 上没有处理器:rc=0,生成源文件 ['PersonBuilder.java'],class ['Main.class', 'Person.class', 'PersonBuilder.class']
[processor] 结束,本处理器共生成 [PersonBuilder]
Note: 为 Person 生成 PersonBuilder(2 个字段)