Detailed java meta-annotation and use custom annotation

1 yuan notes

1.1 What is a meta-annotation

The so-called meta-annotation in fact be able to annotate to comment on other notes, annotated notes called combination notes, combined with its Spring annotation annotation features.

Four kinds of 1.2 yuan notes

Provided in the JDK four standard annotation based on annotation to the annotation types, we call meta-annotation (meta-annotation), they are:

  • @Target
  • @Retention
  • @Documented
  • @Inherited

We can use these four yuan notes to annotate our custom annotation types.

1.3 @Target comment

Target annotation role is to: describe the use of annotations range (ie modified annotation can be used in any place).

Target annotation for explaining that it is annotated based annotation can be modified target range: annotation can be used to modify packages, types (classes, interfaces, enumerations, annotation category), a member of class (method, constructor, member variables, enumeration value), method arguments and local variables (such as a loop variable, the catch parameters), when used @Target annotation class can be defined more clearly know what it can be used to modify the object, which is defined in the range ElementType enumeration.
Source

@Documented  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.ANNOTATION_TYPE)  
public @interface Target {  
    ElementType[] value();  
}  
复制代码

ElementType

public enum ElementType {
 
    TYPE, // 类、接口、枚举类
 
    FIELD, // 成员变量(包括:枚举常量)
 
    METHOD, // 成员方法
 
    PARAMETER, // 方法参数
 
    CONSTRUCTOR, // 构造方法
 
    LOCAL_VARIABLE, // 局部变量
 
    ANNOTATION_TYPE, // 注解类
 
    PACKAGE, // 可用于修饰:包
 
    TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
 
    TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
 
}
复制代码

1.4 @Retention

Reteniton annotation function is: annotation described retention time (i.e.: annotations are described in the modification of its class to be retained when).

Reteniton annotation is used to annotate classes are limited to those annotated notes to it after the other classes, may be retained until when, a total of three strategies, as defined in RetentionPolicy enumeration.
RetentionPolicy

public enum RetentionPolicy {
 
    SOURCE,    // 源文件保留
    CLASS,       // 编译期保留,默认值
    RUNTIME   // 运行期保留,可通过反射去获取注解信息
}
复制代码

Life cycle length SOURCE <CLASS <RUNTIME, where the latter the former can effect must also be able to effect. If desired to obtain dynamically at runtime annotation information, it would only use RUNTIME annotations; if you want some preprocessing operations at compile time, generating a number of such ancillary code (e.g. ButterKnife), to use CLASS annotation; if only do some checking of operations, such as @Override and @SuppressWarnings, you can choose SOURCE comment.

1.5 @Documented

Documented annotation role: as described in the class to generate help files using the javadoc tool if you want to keep its annotation information.
Verify here @Documented role, we create a custom annotation:

@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyDocumentedt {

    public String value() default "这是@Documented注解为文档添加的注释";

}
复制代码

Then create a test class in the methods and classes are custom add comments

@MyDocumentedt
public class MyDocumentedTest {
    /**
     * 测试 document
     * @return String the response
     */
    @MyDocumentedt
    public String test(){
        return "sdfadsf";
    }
}
复制代码

Open the directory where the java file, open a command line, type:

javac .\MyDocumentedt.java .\MyDocumentedTest.java
复制代码
javadoc -d doc .\MyDocumentedTest.java .\MyDocumentedt.java
复制代码

Open the generated doc folder, open index.html , can be found on the classes and methods are retained MyDocumentedt annotation information.

1.6 @Inherited

Inherited annotation role is: to make it to be modified notes are inherited (If a class uses the annotation is @Inherited modified, it will automatically have a subclass of the notes).
To verify through the code, create a custom annotation

@Target({ElementType.TYPE})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MyInherited {
}
复制代码

verification

@MyInherited
public class A {
    public static void main(String[] args) {
        System.out.println(A.class.getAnnotation(MyInherited.class));
        System.out.println(B.class.getAnnotation(MyInherited.class));
        System.out.println(C.class.getAnnotation(MyInherited.class));
    }
}

class B extends A{
}

class C extends B{
}
复制代码

Execute the main method, you can see information about printing from the console

1.7 Repeat annotation @Repeatable

Repeat annotation : i.e., allows the use of a plurality of times before the same annotation type declaration types (class, property or method).

In java8 ago, with the former a program element can only have a maximum of the same type of comment; If more than one of the same type of notes in front of the same element, you must use the annotation "container." Before the practice of java8

public @interface Roles {
    Role[] roles();
}
复制代码
public @interface Roles {
    Role[] value();
}
复制代码
public class RoleAnnoTest {
    @Roles(roles = {@Role(roleName = "role1"), @Role(roleName = "role2")})
    public String doString(){
        return "";
    }
}
复制代码

java8 increased after repeated notes, used as follows:

public @interface Roles {
    Role[] value();
}
复制代码
@Repeatable(Roles.class)
public @interface Role {
    String roleName();
}
复制代码
public class RoleAnnoTest {
    @Role(roleName = "role1")
    @Role(roleName = "role2")
    public String doString(){
        return "";
    }
}
复制代码

The difference is, when you create duplicate notes Role, plus @Repeatable, pointing storage notes Roles, when in use, can be reused directly Role comment. Seen from the above example, java 8 which is more suitable for the practice of conventional thinking, it readable. However, it still needs to be defined container notes.

The same effect is obtained by the two methods. Repeat annotation is just a simplified wording, which simplifies writing is an illusion: in fact, more duplicate notes will be treated as an array element "container" annotation value members.

1.8 type annotations

Java8 ElementType enumeration is increased two enumerated values ​​TYPE_PARAMETER, TYPE_USE, annotations can be defined using the modified @Target (ElementType_TYPE_USE), this type of annotation is called annotations can be used anywhere in the type.

In java8 ago, notes can only be used on a variety of program elements (defined class that defines the interface, define methods, the definition of member variables ...). From java8 Start, type annotations can be used anywhere to type.

TYPE_PARAMETER : indicates that the notes can be written on the declaration type parameters.

TYPE_USE : represents the type of annotation can be used in place of any further use, such as allowing the use of the following positions:

  • Create objects (created with the new keyword)
  • Type Conversion
  • Implement an interface using the implements
  • Use throws a statement exception is thrown
public class TypeUserTest {

    public static void main(String[] args) {
        String str = "str";
        Object obj = (@isNotNull Object) str;
    }

}

@Target(ElementType.TYPE_USE)
@interface isNotNull{
}
复制代码

This pervasive annotation allows the compiler to perform stricter code inspection, thereby improving the robustness of the program.

2 custom annotation

Through the above study has begun to understand the meta-annotation is how one thing, the following line and a custom annotations in context. Custom annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Name {

    public String value() default "";
}
复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sex {

    public enum GenderType {
        Male("男"),
        Female("女");
        private String genderStr;
        private GenderType(String arg0) {
            this.genderStr = arg0;
        }
        @Override
        public String toString() {
            return genderStr;
        }
    }
    GenderType gender() default GenderType.Male;
}
复制代码

Entity class custom annotations

@Data
public class User {

    @Name(value = "wtj")
    public String name;
    public String age;
    @Sex(gender = Sex.GenderType.Male)
    public String sex;

}
复制代码

test

public class AnnotionUtils {

    public static String getInfo(Class<?> cs){
        String result = "";
        //通过反射获取所有声明的字段
        Field[] declaredFields = cs.getDeclaredFields();
        //获取所有字段
        for (Field field : declaredFields){
            if(field.isAnnotationPresent(Name.class)){
                //获取程序元素上的注解
                Name annotation = field.getAnnotation(Name.class);
                String value = annotation.value();
                result += (field.getName() + ":" + value + "\n");
            }
            if(field.isAnnotationPresent(Sex.class)){
                Sex annotation = field.getAnnotation(Sex.class);
                String value = annotation.gender().name();
                result += (field.getName() + ":" + value + "\n");
            }
        }
        return result;
    }

    public static void main(String[] args){
        String info = getInfo(User.class);
        System.out.println(info);
    }

}
复制代码

The main method to run after you can see in the console when the incoming data using the annotation.
Above is a simple annotation using the demo, of course, be used in the actual work will be relatively complex, which we need based on business requirements and Code and use the package needs a custom annotations.

Guess you like

Origin juejin.im/post/5d7f34b3f265da03ee6a894c