• Spring Boot 2 实践记录之 组合注解原理


    Spring 的组合注解功能,网上有很多文章介绍,不过都是介绍其使用方法,鲜有其原理解析。

    组合注解并非 Java 的原生能力。就是说,想通过用「注解A」来注解「注解B」,再用「注解B」 来注解 C(类或方法),就能够使 C 同时拥有「注解A」和「注解B」是行不通的。

    示例如下:

    先定义注解 SuperAnno:

    import java.lang.annotation.*;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SuperAnno {
    }

    再定义注解 SubAnno,并使用 SuperAnno 注解 SubAnno:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @SuperAnno
    @SomeAnno
    public @interface SubAnno {
    }

    定义 Test,使用 SubAnno 注解 Test:

    @SubAnno
    public class Test {
    
    }

    测试一下,看看我们能不能拿到 Test 的 SuperAnno 注解:

    import java.lang.annotation.Annotation;
    
    public class Main {
    
        public static void main(String[] args) {
        // write your code here
            Test test = new Test();
            Class<?> cl = test.getClass();
            Annotation[] annotations = cl.getAnnotations();
            for(Annotation annotation: annotations) {
                System.out.println(annotation.annotationType());
            }
        }
    }

    打印出来的结果为:

    interface com.company.SubAnno

    唔,SuperAnno 没有出现。

    怎么拿到合并的注解呢?

    核心的思路就是拿到注解后,递归获取其上的注解,见下例:

    import javax.annotation.*;
    import java.lang.annotation.*;
    import java.util.ArrayList;
    
    public class Main {
    
        private ArrayList<Annotation> annos = new ArrayList<>();
    
        public static void main(String[] args) {
        // write your code here
            Test test = new Test();
            Class<?> cl = test.getClass();
            Main main = new Main();
            main.getAnnos(cl);
            for(Annotation anno: main.annos) {
                System.out.println(anno.annotationType());
            }
        }
    
        private void getAnnos(Class<?> cl) {
            Annotation[] annotations = cl.getAnnotations();
            for(Annotation annotation: annotations) {
                if (annotation.annotationType() != Deprecated.class &&
                        annotation.annotationType() != SuppressWarnings.class &&
                        annotation.annotationType() != Override.class &&
                        annotation.annotationType() != PostConstruct.class &&
                        annotation.annotationType() != PreDestroy.class &&
                        annotation.annotationType() != Resource.class &&
                        annotation.annotationType() != Resources.class &&
                        annotation.annotationType() != Generated.class &&
                        annotation.annotationType() != Target.class &&
                        annotation.annotationType() != Retention.class &&
                        annotation.annotationType() != Documented.class &&
                        annotation.annotationType() != Inherited.class
                ) {
                    annos.add(annotation);
                    getAnnos(annotation.annotationType());
                }
            }
        }
    }
  • 相关阅读:
    GeoMesa Java API-写入与查询数据
    GeoMesa命令行,索引概述
    HBase,以及GeoMesa设计基于HBase的设计分析,从数据模型到典型查询场景,最后进行RowKey设计
    笔趣看小说Python3爬虫抓取
    python网络爬虫
    Kafka客户端Producer与Consumer
    ScalikeJDBC,操作mysql数据,API
    mysqldb
    Python 反射
    Go 类型转换
  • 原文地址:https://www.cnblogs.com/matchless/p/10388184.html
Copyright © 2020-2023  润新知