주석으로이 작업을 수행 할 수 있습니다!
오류를 발생 시키려면를 사용 Messager
하여 Diagnostic.Kind.ERROR
. 간단한 예 :
processingEnv.getMessager().printMessage(
Diagnostic.Kind.ERROR, "Something happened!", element);
이것을 테스트하기 위해 작성한 상당히 간단한 주석이 있습니다.
이 @Marker
주석은 대상이 마커 인터페이스임을 나타냅니다.
package marker;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Marker {
}
주석 프로세서는 다음과 같지 않은 경우 오류를 발생시킵니다.
package marker;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
import javax.tools.Diagnostic;
import java.util.Set;
@SupportedAnnotationTypes("marker.Marker")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public final class MarkerProcessor extends AbstractProcessor {
private void causeError(String message, Element e) {
processingEnv.getMessager()
.printMessage(Diagnostic.Kind.ERROR, message, e);
}
private void causeError(
Element subtype, Element supertype, Element method) {
String message;
if (subtype == supertype) {
message = String.format(
"@Marker target %s declares a method %s",
subtype, method);
} else {
message = String.format(
"@Marker target %s has a superinterface " +
"%s which declares a method %s",
subtype, supertype, method);
}
causeError(message, subtype);
}
@Override
public boolean process(
Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
Elements elementUtils = processingEnv.getElementUtils();
boolean processMarker = annotations.contains(
elementUtils.getTypeElement(Marker.class.getName()));
if (!processMarker)
return false;
for (Element e : roundEnv.getElementsAnnotatedWith(Marker.class)) {
ElementKind kind = e.getKind();
if (kind != ElementKind.INTERFACE) {
causeError(String.format(
"target of @Marker %s is not an interface", e), e);
continue;
}
if (kind == ElementKind.ANNOTATION_TYPE) {
causeError(String.format(
"target of @Marker %s is an annotation", e), e);
continue;
}
ensureNoMethodsDeclared(e, e);
}
return true;
}
private void ensureNoMethodsDeclared(
Element subtype, Element supertype) {
TypeElement type = (TypeElement) supertype;
for (Element member : type.getEnclosedElements()) {
if (member.getKind() != ElementKind.METHOD)
continue;
if (member.getModifiers().contains(Modifier.STATIC))
continue;
causeError(subtype, supertype, member);
}
Types typeUtils = processingEnv.getTypeUtils();
for (TypeMirror face : type.getInterfaces()) {
ensureNoMethodsDeclared(subtype, typeUtils.asElement(face));
}
}
}
예를 들어, 다음은 올바른 용도입니다 @Marker
.
그러나 이러한 사용으로 @Marker
인해 컴파일러 오류가 발생합니다.
다음은 주제를 시작하는 데 매우 도움이되는 블로그 게시물입니다.
작은 메모 : 아래 주석가가 지적한 것은 MarkerProcessor
reference 이므로 Marker.class
컴파일 시간에 종속된다는 것입니다. 두 클래스가 동일한 JAR 파일 (예 :)에 들어갈 것이라는 가정하에 위의 예제를 작성 marker.jar
했지만 항상 가능한 것은 아닙니다.
예를 들어, 다음 클래스가있는 애플리케이션 JAR이 있다고 가정하십시오.
com.acme.app.Main
com.acme.app.@Ann
com.acme.app.AnnotatedTypeA (uses @Ann)
com.acme.app.AnnotatedTypeB (uses @Ann)
그런 다음에 대한 프로세서 @Ann
는 애플리케이션 JAR을 컴파일하는 동안 사용되는 별도의 JAR에 있습니다.
com.acme.proc.AnnProcessor (processes @Ann)
이 경우 순환 JAR 종속성을 생성하므로 AnnProcessor
유형을 @Ann
직접 참조 할 수 없습니다 . 그것은 단지 참조 할 수있을 것 @Ann
으로 String
이름이나 TypeElement
/ TypeMirror
.