如何使注释仅在一个目标上弃用

时间:2013-12-30 13:09:47

标签: java annotations deprecated

我有一个可以添加到METHODTYPE的注释,并在我们项目的数千个地方使用。

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD, TYPE})
@Inherited
public @interface RequiredStore{
    Store value();
}

是否可以仅在方法上弃用注释,同时在类型上保持不推荐使用?我希望IDE通知其他开发人员它不应再用于方法,直到我们重构所有现有用法并最终删除METHOD部分。

如果不可能,除了仅为类型创建新注释并弃用旧注释外,还有办法处理这种情况吗?

2 个答案:

答案 0 :(得分:5)

您可以使用注释Processor

例如,注释及其处理器将放在其自己的.jar文件中,并作为使用注释的源的依赖项添加。

自定义.jar具有以下结构:

src/main/
    java/com/company/annotations/
        RequiredStore.java
        RequiredStoreProcessor.java
    resources/META-INF/services
        javax.annotation.processing.Processor

RequiredStore.java保持原样。

RequiredStoreProcessor.java看起来像这样:

package com.company.annotations;

import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
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.tools.Diagnostic;

@SupportedAnnotationTypes("com.company.annotations.RequiredStore")
public class RequiredStoreProcessor extends AbstractProcessor {
    @Override
    public boolean process(
            Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        for (Element element 
                : roundEnv.getElementsAnnotatedWith(RequiredStore.class)) {
            if (element.getKind().equals(ElementKind.METHOD)) {
                processingEnv.getMessager().printMessage(
                    Diagnostic.Kind.WARNING,
                    "Using @RequiredStore on methods has been deprecated\n"
                        + "Class: " + element.getEnclosingElement() + "\n"
                        + "Method: " + element.getSimpleName() + "\n");
            }
        }

        // Other processing...

        return false;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
    }
}

javax.annotation.processing.Processor文件允许javac通过SPI拾取处理器,只包含

com.company.annotations.RequiredStoreProcessor

最后,将其编译为.jar并将其添加到使用注释的类路径中。任何具有@RequiredStore的方法都会产生编译器警告。例如,对于这个类,

package com.company.business;

import com.company.annotations.RequiredStore;

@RequiredStore
public interface Business {
    @RequiredStore
    public void someMethod();
}

编译器警告是这样的:

warning: Using @RequiredStore on methods has been deprecated
  Class: com.company.business.Business
  Method: someMethod   

至于IDE中的指示,您可能必须编写自定义检查,不幸的是,这取决于所使用的IDE。


说明:

体面的自定义注释参考:Code Generation using Annotation Processors in the Java language

答案 1 :(得分:2)

如果你可以使用native aspectj,另一个选择就是以这种方式使用AspectJ的代码执行策略:

public aspect RequiredStoreAnnotationCheck {

    declare warning: execution(@RequiredStore * *.*(..)) : "Required store annotation not    appropriate for methods..";

}

如果IDE与AspectJ集成,则会将其标记为编译时检查。

行动手册中的AspectJ也有很多细节。

以下是我的博客文章之一,内容更多:http://www.java-allandsundry.com/2012/03/code-policy-enforcement-using-aspectj.html