使用註釋處理器編譯時間處理
此示例演示如何對帶註釋的元素進行編譯時檢查。
註釋
@Setter
註釋是可以應用於方法的標記。註釋將在編譯期間被丟棄,之後無法使用。
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface Setter {
}
註釋處理器
編譯器使用 SetterProcessor
類來處理註釋。如果使用 @Setter
註釋註釋的方法是 public
,則檢查名稱以 set
開頭且大寫字母為第 4 個字母的非 static
方法。如果不滿足其中一個條件,則會向 Messager
寫入錯誤。編譯器將此寫入 stderr,但其他工具可能以不同方式使用此資訊。例如,NetBeans IDE 允許使用者指定用於在編輯器中顯示錯誤訊息的註釋處理器。
package annotation.processor;
import annotation.Setter;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
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.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
@SupportedAnnotationTypes({"annotation.Setter"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class SetterProcessor extends AbstractProcessor {
private Messager messager;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// get elements annotated with the @Setter annotation
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(Setter.class);
for (Element element : annotatedElements) {
if (element.getKind() == ElementKind.METHOD) {
// only handle methods as targets
checkMethod((ExecutableElement) element);
}
}
// don't claim annotations to allow other processors to process them
return false;
}
private void checkMethod(ExecutableElement method) {
// check for valid name
String name = method.getSimpleName().toString();
if (!name.startsWith("set")) {
printError(method, "setter name must start with \"set\"");
} else if (name.length() == 3) {
printError(method, "the method name must contain more than just \"set\"");
} else if (Character.isLowerCase(name.charAt(3))) {
if (method.getParameters().size() != 1) {
printError(method, "character following \"set\" must be upper case");
}
}
// check, if setter is public
if (!method.getModifiers().contains(Modifier.PUBLIC)) {
printError(method, "setter must be public");
}
// check, if method is static
if (method.getModifiers().contains(Modifier.STATIC)) {
printError(method, "setter must not be static");
}
}
private void printError(Element element, String message) {
messager.printMessage(Diagnostic.Kind.ERROR, message, element);
}
@Override
public void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
// get messager for printing errors
messager = processingEnvironment.getMessager();
}
}
打包
要由編譯器應用,需要使註釋處理器可用於 SPI(請參閱 ServiceLoader )。
為此,除了其他檔案之外,還需要將文字檔案 META-INF/services/javax.annotation.processing.Processor
新增到包含註釋處理器和註釋的 jar 檔案中。該檔案需要包含註釋處理器的完全限定名稱,即它應該如下所示
annotation.processor.SetterProcessor
我們假設 jar 檔案在下面被稱為 AnnotationProcessor.jar
示例註釋類
以下類是預設包中的示例類,其中註釋根據保留策略應用於正確的元素。但是,只有註釋處理器才將第二種方法視為有效的註釋目標。
import annotation.Setter;
public class AnnotationProcessorTest {
@Setter
private void setValue(String value) {}
@Setter
public void setString(String value) {}
@Setter
public static void main(String[] args) {}
}
使用帶有 javac 的註釋處理器
如果使用 SPI 發現註釋處理器,則會自動使用它來處理帶註釋的元素。例如,使用編譯 AnnotationProcessorTest
類
javac -cp AnnotationProcessor.jar AnnotationProcessorTest.java
產生以下輸出
AnnotationProcessorTest.java:6: error: setter must be public
private void setValue(String value) {}
^
AnnotationProcessorTest.java:12: error: setter name must start with "set"
public static void main(String[] args) {}
^
2 errors
而不是正常編譯。沒有建立 .class
檔案。
這可以通過為 javac
指定 -proc:none
選項來防止。你也可以通過指定 -proc:only
來放棄通常的編譯。
IDE 整合
Netbeans
註釋處理器可以在 NetBeans 編輯器中使用。為此,需要在專案設定中指定註釋處理器:
-
去
Project Properties
>Build
>Compiling
-
為
Enable Annotation Processing
和Enable Annotation Processing in Editor
新增複選標記 -
單擊註釋處理器列表旁邊的
Add
-
在出現的彈出視窗中輸入註釋處理器的完全限定類名,然後單擊
Ok
。