美文网首页
2021-06-14_Java 注解(Annotation)

2021-06-14_Java 注解(Annotation)

作者: 微笑碧落 | 来源:发表于2021-06-13 11:18 被阅读0次

    0.前言

    • Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
    • 类、方法、变量、参数和包都可以增加注解
    • Java 虚拟机可以保留标注内容,在运行时可以获取到注解内容
    • 注解已经是大行其道了,在很多第三方框架上都有注解的身影。
    • 通过增加注解。给该元素附加一些额外的说明。
    • 注解主要是在反射中使用,可以通过注解获得元素的各种注解。通过注解附加的信息进行一些操作。对于解耦很有帮助。
    • 注解类本身是一种特殊的类。自定义了一个注解类后,就可以在代码中通过@Annotation来使用它
    • 注意。。注意。。。注解和反射都是针对类而言。。。对不同对象同一个类进行反射,得到同样的一个个field,method,class对象。这个可以参照第4点来理解,第4点可以动态修改整改类的注解。

    1.注解类的声明

    • 其中@Target@Retention为注解类的注解
    • @Target,表明该注解类的作用范围。一个注解类可以有多个@Target注解
    • @Retention,表明注解的保持范围,一般为RUNTIME。一个注解类仅仅只能有一个@Retention
    • String editor() default "TextFieldTableCell";该语句声明了一个特殊的方法。该方法名称为editor(),范围值类型为String,默认值为 "TextFieldTableCell"
    • 一个注解类可以声明多个方法,每个方法的返回值类型可以多种多样,如枚举,某个对象,甚至是class对象。
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation1 {
        String editor() default "TextFieldTableCell";
        String[] optionalValue() default {""};
        RetentionPolicy value();
    }
    
    package java.lang.annotation;
    public enum RetentionPolicy {
        SOURCE,            /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了  */
        CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */
        RUNTIME            /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
    }
    
    package java.lang.annotation;
    public enum ElementType {
        TYPE,               /* 类、接口(包括注释类型)或枚举声明  */
        FIELD,              /* 字段声明(包括枚举常量)  */
        METHOD,             /* 方法声明  */
        PARAMETER,          /* 参数声明  */
        CONSTRUCTOR,        /* 构造方法声明  */
        LOCAL_VARIABLE,     /* 局部变量声明  */
        ANNOTATION_TYPE,    /* 注释类型声明  */
        PACKAGE             /* 包声明  */
    }
    

    2.注解类的使用

    • 声明了一个注解类后,就可以在对象的元素中使用了。
    • 对注解的方法进行赋值,有点类似于对变量进行赋值的语句,只是多个方法赋值语句用,分开。以下例子,展示了字符串,class对象,字符串数组的赋值语句。
    • value方法的赋值,该方法可以省略等号左边的方法名称。如@Retention(RetentionPolicy.RUNTIME)
    • 注解类的使用,可以理解为定义了一个注解对象。该注解对象,带有附加信息的属性值。
    @Entity
    @Table(name = "missions")
    @TableIncludeIndexColumn(name = "序号")
    @Convert(converter = StringPropertyConvertor.class)
    public class Mission {
        @Id
        @Column(name = "id")
        @GeneratedValue(generator = "uuid")
        @GenericGenerator(name = "uuid", strategy = "uuid")
        private String id;
    
         @ColumnDescribe(name = "停电类型", index = 3, editor = "ComboBoxTableCell", optionalValue = {"停电","不停电","带电"})
        @Convert(converter = StringPropertyConvertor.class)
        private StringProperty missionDate;
    }
    

    3. 通过反射获取一个元素的注解

    • 这里需要了解下反射知识,才能更好的理解
    • 如下例子,是获取一个类的注解,当然对于方法或变量也是同样处理。这些类和方法和变量被包装成一个个field,method,class对象
    • 注意,之前声明的是一个注解类,如下方法获得一个注解对象。可以通过这个注解对象访问注解的方法,获得注解值。
    Class theClass = Class.forName("homework01.User");
    Class missionClass = Mission.class;
    boolean hasAnn = theClass.isAnnotationPresent(MyAnnotation.class)
    
    //获取一个注解对象
    MyAnnotation myAnn = theClass.getAnnotation(MyAnnotation.class);
    
    //获取全部类方法,并通过是否有注解来筛选
    Arrays.stream(modelClass.getDeclaredFields())
                    .filter(field -> field.getAnnotation(ColumnDescribe.class) != null)
    
    

    4. 动态修改注解值

    • 如下代码事实上是利用了反射。
    • 对注解代理对象进行反射,修改该对象的表示注解元素的变量值。
    ColumnDescribe annotation = Mission.class.getDeclaredField("missionType").getAnnotation(ColumnDescribe.class);
    System.out.println("修改前:" + annotation.index());
    
    InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
    
    Field value = invocationHandler.getClass().getDeclaredField("memberValues");
    value.setAccessible(true);
    Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler);
    memberValues.put("index",999);
    System.out.println("修改后:" +annotation.index());
    

    参考文章

    1.Java 注解(Annotation)
    2.反射机制获取一个类的注解
    3.[Java] 通过反射,动态修改注解的某个属性值

    相关文章

      网友评论

          本文标题:2021-06-14_Java 注解(Annotation)

          本文链接:https://www.haomeiwen.com/subject/mzbneltx.html