修改 HandleableProcessor.java 类,以添加如下代码。保存所做的更改。
package proc;
import ann.Handleable;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
@SupportedAnnotationTypes("ann.Handleable")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class HandleableProcessor extends AbstractProcessor {
/** public for ServiceLoader */
public HandleableProcessor() {
}
public boolean process(Set extends TypeElement> annotations,
RoundEnvironment roundEnv) {
for (Element e : roundEnv.getElementsAnnotatedWith(Handleable.class)) {
if (e.getKind() != ElementKind.FIELD) {
processingEnv.getMessager().printMessage(
Diagnostic.Kind.WARNING,
"Not a field", e);
continue;
}
String name = capitalize(e.getSimpleName().toString());
TypeElement clazz = (TypeElement) e.getEnclosingElement();
try {
JavaFileObject f = processingEnv.getFiler().
createSourceFile(clazz.getQualifiedName() + "Extras");
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
"Creating " + f.toUri());
Writer w = f.openWriter();
try {
PrintWriter pw = new PrintWriter(w);
pw.println("package "
+ clazz.getEnclosingElement().getSimpleName() + ";");
pw.println("public abstract class "
+ clazz.getSimpleName() + "Extras {");
pw.println(" protected " + clazz.getSimpleName()
+ "Extras() {}");
TypeMirror type = e.asType();
pw.println(" /** Handle something. */");
pw.println(" protected final void handle" + name
+ "(" + type + " value) {");
pw.println(" System.out.println(value);");
pw.println(" }");
pw.println("}");
pw.flush();
} finally {
w.close();
}
} catch (IOException x) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
x.toString());
}
}
return true;
}
private static String capitalize(String name) {
char[] c = name.toCharArray();
c[0] = Character.toUpperCase(c[0]);
return new String(c);
}
}
让我们详细了解构成标注处理程序代码的主要部分(请注意,为方便起见,我们仅提供了部分代码)。
首先,您指定标注处理程序支持的标注类型(通过 @SupportedAnnotationTypes)以及支持的源文件版本(通过 @SupportedSourceVersion);在本示例中,版本为 JDK 6:
@SupportedAnnotationTypes("ann.Handleable")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
然后,为处理程序声明一个公共类,以扩展 javax.annotation.processing 包中的 AbstractProcessor 类。AbstractProcessor 是具体标注处理程序的标准超类,它包含处理标注所需的方法。
public class HandleableProcessor extends AbstractProcessor {
...
}
现在,您需要为该类提供一个公共构造函数。
public class HandleableProcessor extends AbstractProcessor {
public HandleableProcessor() {
}
...
}
然后,调用父 AbstractProcessor 类的 process() 方法。通过此方法,提供可用于处理的标注。此外,此方法包含有关处理舍入的信息。
public class HandleableProcessor extends AbstractProcessor {
...
public boolean process(Set extends TypeElement> annotations,
RoundEnvironment roundEnv) {
...
}
}
标注处理程序的逻辑包含在 AbstractProcessor 类的 process() 方法中。注意:通过 AbstractProcessor,还可以访问 ProcessingEnvironment 接口,该接口允许标注处理程序使用多个有用的工具,如 Filer(使标注处理程序可以创建新文件的 Filer 处理程序)和 Messager(标注处理程序报告错误的一种方式)。
public class HandleableProcessor extends AbstractProcessor {
...
public boolean process(Set extends TypeElement> annotations,
RoundEnvironment roundEnv) {
//For each element annotated with the Handleable annotation
for (Element e : roundEnv.getElementsAnnotatedWith(Handleable.class)) {
//Check if the type of the annotated element is not a field. If yes, return a warning.
if (e.getKind() != ElementKind.FIELD) {
processingEnv.getMessager().printMessage(
Diagnostic.Kind.WARNING,
"Not a field", e);
continue;
}
//Define the following variables: name and clazz.
String name = capitalize(e.getSimpleName().toString());
TypeElement clazz = (TypeElement) e.getEnclosingElement();
//Generate a source file with a specified class name.
try {
JavaFileObject f = processingEnv.getFiler().
createSourceFile(clazz.getQualifiedName() + "Extras");
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
"Creating " + f.toUri());
Writer w = f.openWriter();
//Add the content to the newly generated file.
try {
PrintWriter pw = new PrintWriter(w);
pw.println("package "
+ clazz.getEnclosingElement().getSimpleName() + ";");
pw.println("public abstract class "
+ clazz.getSimpleName() + "Extras {");
pw.println(" protected " + clazz.getSimpleName()
+ "Extras() {}");
TypeMirror type = e.asType();
pw.println(" /** Handle something. */");
pw.println(" protected final void handle" + name
+ "(" + type + " value) {");
pw.println(" System.out.println(value);");
pw.println(" }");
pw.println("}");
pw.flush();
} finally {
w.close();
}
} catch (IOException x) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
x.toString());
}
}
return true;
}
...
}
此代码的最后一段代码块声明了 capitalize 方法,该方法用于大写标注的元素的名称。
public class HandleableProcessor extends AbstractProcessor {
...
private static String capitalize(String name) {
char[] c = name.toCharArray();
c[0] = Character.toUpperCase(c[0]);
return new String(c);
}
}