• Java之Annotation(注解)——注解处理器


    如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。


    注解处理器类库(java.lang.reflect.AnnotatedElement): 
      Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:

    • Class:类定义 - Constructor:构造器定义
    • Field:类的成员变量定义
    • Method:类的方法定义
    • Package:类的包定义

    java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。

    AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个方法来访问Annotation信息:

    方法1: T getAnnotation(Class annotationClass): 返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。 
    方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。 
    方法3:boolean is AnnotationPresent(Class< ?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false. 
    方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

    一个简单的注解处理器:

    /***********注解声明***************/
    
    /**
     * 水果名称注解
    
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FruitName {
        String value() default "";
    }
    
    /**
     * 水果颜色注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FruitColor {
        /**
         * 颜色枚举
         */
        public enum Color {
            BULE, RED, GREEN
        };
    
        /**
         * 颜色属性
         */
        Color fruitColor() default Color.GREEN;
    
    }
    
    /**
     * 水果供应者注解
     * 
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FruitProvider {
        /**
         * 供应商编号
         */
        public int id() default -1;
    
        /**
         * 供应商名称
         */
        public String name() default "";
    
        /**
         * 供应商地址
         */
        public String address() default "";
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    /*********** 注解使用 ***************/
    
    public class Apple {
    
        @FruitName("Apple")
        private String appleName;
    
        @FruitColor(fruitColor = Color.RED)
        private String appleColor;
    
        @FruitProvider(id = 1, name = "香蕉集团", address = "广东省水果大厦")
        private String appleProvider;
    
        public void setAppleColor(String appleColor) {
            this.appleColor = appleColor;
        }
    
        public String getAppleColor() {
            return appleColor;
        }
    
        public void setAppleName(String appleName) {
            this.appleName = appleName;
        }
    
        public String getAppleName() {
            return appleName;
        }
    
        public void setAppleProvider(String appleProvider) {
            this.appleProvider = appleProvider;
        }
    
        public String getAppleProvider() {
            return appleProvider;
        }
    
        public void displayName() {
            System.out.println("水果的名字是:苹果");
        }
    }
    /*********** 注解处理器 ***************/
    
    public class FruitInfoUtil {
        public static void getFruitInfo(Class<?> clazz) {
    
            String strFruitName = " 水果名称:";
            String strFruitColor = " 水果颜色:";
            String strFruitProvicer = "供应商信息:";
    
            Field[] fields = clazz.getDeclaredFields();
    
            for (Field field : fields) {
                if (field.isAnnotationPresent(FruitName.class)) {
                    FruitName fruitName = (FruitName) field
                            .getAnnotation(FruitName.class);
                    strFruitName = strFruitName + fruitName.value();
                    System.out.println(strFruitName);
                } else if (field.isAnnotationPresent(FruitColor.class)) {
                    FruitColor fruitColor = (FruitColor) field
                            .getAnnotation(FruitColor.class);
                    strFruitColor = strFruitColor
                            + fruitColor.fruitColor().toString();
                    System.out.println(strFruitColor);
                } else if (field.isAnnotationPresent(FruitProvider.class)) {
                    FruitProvider fruitProvider = (FruitProvider) field
                            .getAnnotation(FruitProvider.class);
                    strFruitProvicer = " 供应商编号:" + fruitProvider.id() + " 供应商名称:"
                            + fruitProvider.name() + " 供应商地址:"
                            + fruitProvider.address();
                    System.out.println(strFruitProvicer);
                }
            }
        }
    }
    /***********main方法***************/
    public class FruitRun {
    
    
        public static void main(String[] args) {
    
            FruitInfoUtil.getFruitInfo(Apple.class);
    
        }
    
    }
    
    /***********输出结果***************/
     水果名称:Apple
     水果颜色:RED
     供应商编号:1 供应商名称:香蕉集团 供应商地址:广东省水果大厦
  • 相关阅读:
    ERROR 1045 (28000): Access denied for user root@localhost (using password:
    MySQL: InnoDB 还是 MyISAM?
    PHP系统函数
    为什么分离数据库软件和数据库服务?
    C#索引器的作用及使用
    asp.net 中Session的运用,及抛出错误“未将对象引用设置到对象的实例”
    C#父类对象和子类对象之间的转化
    C#中属性简写原理
    c# 中Intern的作用
    C# 中ref和out的区别
  • 原文地址:https://www.cnblogs.com/cat520/p/9473013.html
Copyright © 2020-2023  润新知