9

我正在实现一个注释处理器,以确保标有注释的元素是实现某个接口的类的实例,或者是实现某个接口的类型的使用:

@Documented
@Target(value = { ElementType.PARAMETER, ElementType.TYPE_USE })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface AuditSubject {

}

public interface Auditable {
    // methods that provide data for writing a log entry...
}

public class Report implements Auditable {

}

对于带注释的元素,必须在方法执行后创建一个日志条目(使用 AOP)。例子:

@CreateLogEntry
public Result persist(@AuditSubject Report newReport) {
    // A log entry must be created based on the incoming 'newReport' instance.    
}

@CreateLogEntry
public UpdateResult<@AuditSubject Report> update(Report update) {
    // A log entry must be created based on the updated report, which is not the same instance as 'update' but an equivalent one.
} 

@CreateLogEntry
public Result persistBatch(List<@AuditSubject Report> batch) {
    // A log entry must be created for each element in 'batch' after this method's execution.
}

Report如果实现了,则必须创建日志条目Auditable;如果没有,则抛出运行时异常(哎呀,我忘了实现接口!)。因此,注释处理器有助于在编译时捕捉程序员的错误。到目前为止,我已经成功地检查了参数中的所有用途,但没有检查类型用途。注释处理器的相关代码如下:

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    for (Element annotated : roundEnv.getElementsAnnotatedWith(AuditSubject.class)) {
        // Only prints elements with ElementKind.PARAMETER)!
        this.messager.printMessage(Kind.NOTE, TextUtils.replaceParams("annotated: {} ; Kind : {} ; enclosing : {}", annotated,  annotated.getKind(), annotated.getEnclosingElement()));

        if (annotated.getKind() == ElementKind.PARAMETER) {
            // Code here works as expected, raises errors for annotated parameters of classes that don't implement Auditable.
        } else if (annotated.getKind() == ElementKind.WHAT_TO_USE) {
            // What ElementKind do I need to use here?
        }
    }

    return false;
}

只识别带有 kind 的带注释的元素ElementKind.PARAMETER(process() 循环中的第一行只打印一行 for 'newReport')如何检查带注释的类型是否实现Auditable?没有 " ElementKind.TYPE_USE" 常量可以使用。我一直无法找到任何有关此事的信息。感谢您的关注。

4

2 回答 2

4

Java 注释处理 API 是在 Java 仅支持声明上的注释时设计的。API 仅支持访问声明,例如字段、方法和方法参数。它不访问局部变量声明,也不访问方法体中的其他注释,也不访问类型注释。

如果您希望在方法体中处理类型注释或注释,您将需要编写自己的代码来递归类型或递归检查方法中的代码行。

另一种方法是使用Checker Framework之类的工具。它实现了自己的访问者,因此每次出现类型注释时都会调用构建在其上的注释处理器。

于 2017-02-10T17:09:46.143 回答
0

为什么不使用 TYPE_PARAMETER? javax.annotation.processing.ProcessorAPI文档有:

An annotation type is considered present if there is at least one annotation of that type present on an element enclosed within the root elements of a round. For this purpose, a type parameter is considered to be enclosed by its generic element. Annotations on type uses, as opposed to annotations on elements, are ignored when computing whether or not an annotation type is present.

javax.lang.model.element.TypeParameterElement
Element getGenericElement()
Returns the generic class, interface, method, or constructor that is parameterized by this type parameter.
于 2019-11-01T09:50:36.500 回答