java - 如何像FunctionalInterface一样实现注解来限制成员函数的数量、函数类型等?

标签 java annotations

Java内部有很多注解,如SuppressWarningFunctionalInterface等,可以通过注解限制类的成员、扩展类甚至指定编译器选项,但是普通程序员如何编写这样的注释呢?

我搜索了注释主题,我所能找到的只是向注释添加一些元值,例如 this ,以及如何使用注释,但我找不到任何解释如何实现高级注释的内容。任何指示都会有帮助。

最佳答案

您正在寻找的是编译时注释

基本上,注释处理可以基于其RetentionPolicy来完成。根据Java docs ,有 3 种类型的 RetentionPolicy -

CLASS Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.

RUNTIME Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.

SOURCE Annotations are to be discarded by the compiler.

编译时注解处理与RetentionPolicy.SOURCE相关,因为您希望在编译时对源文件进行处理,类似于@Override等其他注解。

下面是一个简单的编译时注释处理器的示例 -

  1. 创建 Maven 项目 - Annotation_Compile_Time -

    (A) 在此项目中创建编译时注释 MyAnnotation -

    package xxx;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Documented
    @Target(ElementType.TYPE)
    @Inherited
    @Retention(RetentionPolicy.SOURCE)
    public @interface MyAnnotation {
    
    }
    

    (B) 创建注释处理器 MyAnnotationProcessor -

    package xxx;
    
    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.TypeElement;
    import javax.tools.Diagnostic;
    
    @SupportedAnnotationTypes("xxx.MyAnnotation ")
    @SupportedSourceVersion(SourceVersion.RELEASE_8)
    public class MyAnnotationProcessor extends AbstractProcessor {
    
        public MyAnnotationProcessor () {
            super();
        }
    
        @Override
        public boolean process(Set<? extends TypeElement> typeElementSet, RoundEnvironment roundEnv) {
    
            for (Element e : roundEnv.getRootElements()) {
                String className = e.toString();
                String message = "Annotated class - " + className;
                System.out.println(message);
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message);
            }
    
            return false;
        }
    }
    

    (C) 在目录 - src/main/resources/META-INF/services 中创建 javax.annotation.processing.Processor 文件包含以下内容 -

    xxx.MyAnnotationProcessor
    

    (D) 使用构建配置更新 pom.xml -

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <verbose>true</verbose>
                    <fork>true</fork>
                    <compilerArgument>-proc:none</compilerArgument>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

    (E) 使用 mvn clean install 编译并安装此项目。

  2. 创建另一个 Maven 项目 - Annotation_User - 该项目将使用上述项目中定义的注释。在此项目中创建 2 个使用此注释进行注释的源文件

    (A) AnnotationUser1 -

    package xxx.consumer;
    
    import xxx.MyAnnotation;
    
    @MyAnnotation
    public class AnnotationUser1 {
    
        private String message;
    
        public AnnotationUser1(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
    }
    

    (B) AnnotationUser2 -

    package xxx.consumer;
    
    import xxx.MyAnnotation;
    
    @MyAnnotation
    public class AnnotationUser2 {
    
        private String message;
    
        public AnnotationUser1(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
    }
    

    (C) 使用注释项目依赖项更新 pom.xml -

    <dependency>
        <groupId>xxx</groupId>
        <artifactId>Annotation_Compile_Time</artifactId>
        <version>1.0</version>
    </dependency>
    

现在,每当您使用 mvn cleancompile 编译此项目时,项目 1 中定义的注释处理器都会被调用。目前,处理器只是打印用此注释注释的类的名称。

您还可以引用this页面了解详细信息。

下一步是分析源文件并计算数量。的方法。因为,它是编译时处理,所以你不能使用Reflection API来获取no。的方法。一种解决方案是使用 Eclipse AST用于解析源文件并计算数量。方法或者您可以编写自己的逻辑。

Project lombok主要是基于Compile-time注解处理。如果你想做一些有用的事情,最好学习Project lombok source code

关于java - 如何像FunctionalInterface一样实现注解来限制成员函数的数量、函数类型等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48570033/

相关文章:

android - @Background 和 screen rotation 使用 AndroidAnnotations 时,如何确保收到回调?

java - Spring boot + OAuth2 安全和请求过滤器

Java继承设计思想 - 求指教

java - 如何在 Java 中将 ArrayList 发送到线程时执行多线程和 Socket 编程

regex - 使用正则表达式自动向 PDF 文件添加注释

java - Hibernate 新手在 netbeans 中的帮助

java - 请评论对称加密中密码 block 链接(CBC)的数据大小

java - 我可以强制我的 Excel 工作簿关闭 Access 数据库连接吗?

java - Spring 4 中有多个@ComponentScan?

java - 在没有 Spring 的情况下使用 AspectJ 注释