Learn Java Annotation Together

Keywords: Java Attribute Excel REST

Catalog

I. what is Annotation?

We see a lot of code like @Override, @SuppressWarnings, @Test and so on in the normal development process. Annotations are tags placed before classes, constructors, methods, attributes and parameters.

II. The role of Annotation

Adding a comment to a class or method. This link only makes a mark, which will not affect the code itself. It needs the cooperation of subsequent links and other methods to give the business logic to the comment. Just as we have shared a location on the web, it is not useful at this time. Only when the rest of us get into this shared location can we know how to get together.

Annotations fall into three categories:

2.1 Annotations used by compilers

For example, @Override, @SuppressWarnings are annotations used by the compiler to tell the compiler something instead of entering the compiled. class file.

@ Override: Tell the compiler to check if the method of the parent class is overridden.

@ Suppress Warnings: Tell the compiler to ignore the warning generated by this code;

For developers, it's all direct use, no other operation is required.

2.2. Annotations used in the class file

Some annotations need to be modified by tools. Some tools will dynamically modify annotated. class files when classes are loaded, so as to realize some special functions. After one-time processing, they will not exist in memory. They are all very low-level tool libraries and frameworks that will be used. Generally, for developers, they will not be involved. Here.

2.3 Annotations read during runtime

Annotations that have always existed in JVM and can be read during runtime are also the most commonly used annotations, such as Spring's @Controller, @Service, @Repository, @AutoWired, Mybatis'Mapper, Junit's @Test, etc. Many of these annotations are tool frameworks that customize annotations that play a special role during runtime, and developers can customize such annotations.

Definition of Annotation

We use @interface to define an annotation

/**
 * Define a Table annotation
 */
public @interface Table {
    String value() default "";
}
/**
 * Define a Colum annotation
 */
public @interface Colum {
    String value() default "";
    String name() default "";
    String dictType() default "";
}

This simply defines an annotation.

The annotations we defined above are mainly for String types, but in fact they can also be basic data types (not wrapper classes), enumeration types.

Annotations also have a convention that the most commonly used parameter should be named value, and in general we set a default value through the default parameter.

But is that enough for our use? I want to use the @Table annotation only on classes and the @Colum annotation only on attributes. What should I do? And the three types of annotations mentioned at the beginning are runtime annotations, which are commonly used by developers. Are we defining them?

To answer these questions, we need to introduce a concept of "meta-annotation".

3.1 Yuan Annotation

Annotations that can modify annotations are meta-annotations. Java has defined some meta-annotations that we can use directly.

3.1.1 @Target

As the name implies, specify the target object for the annotation, with the parameter ElementType []

public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

The following are the properties defined in the ElementType enumeration. When Target is not set, other places are equivalent to configuration except TYPE_PARAMETER and TYPE_USE.

public enum ElementType {
    /** Classes, interfaces, enumerations can be modified by ElementType.TYPE */
    TYPE,

    /** Class attributes can be modified by ElementType.FIELD */
    FIELD,

    /** Method can be modified by ElementType.METHOD */
    METHOD,

    /** Parameters (such as constructors or methods) can be modified by ElementType.PARAMETER */
    PARAMETER,

    /** Constructors can be modified through ElementType.CONSTRUCTOR */
    CONSTRUCTOR,

    /** ElementType.LOCAL_VARIABLE modifies local variables within a method */
    LOCAL_VARIABLE,

    /** Annotations can be modified by ElementType.ANNOTATION_TYPE */
    ANNOTATION_TYPE,

    /** Packages can be modified with ElementType.PACKAGE */
    PACKAGE,

    /**
     * It can be used before the declaration of Type
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Can be used in all places where Type is used (such as generics, type conversions, etc.)
     *
     * @since 1.8
     */
    TYPE_USE
}

Let's talk about ElementType.PACKAGE and ElementType.TYPE_PARAMETER and ElementType.TYPE_USE added in 1.8.

ElementType.PACKAGE

@Target(ElementType.PACKAGE)
public @interface Table {
    String value() default "";
}

The meaning is used to modify packages, but when we modify packages, we prompt errors.

Let's create the package-info.java file as prompted. Here we need to note that new - > Java Class can't be created through IDE. It needs to be created through the new File file.

@Table
package annotation;
class PackageInfo {
    public void hello() {
        System.out.println("hello");
    }
}

ElementType.TYPE_PARAMETER and ElementType.TYPE_USE

The two said together because they have similarities. All added after Java 1.8

@Target(ElementType.TYPE_USE)
public @interface NoneEmpty {
    String value() default "";
}
@Target(ElementType.TYPE_PARAMETER)
public @interface NoneBlank {
    String value() default "";
}

It is obvious that the annotation @NoneBlank modified with ElementType.TYPE_PARMETER can not be compiled and passed when generics are used, but can only be used for generic declarations of classes, whereas the annotation @NoneEmpty modified with ElementType.TYPE_USE can.

3.1.2 @Retention

It can be used to define the life cycle of annotations by enumerating Retention Policy, including SOURCE,CLASS,RUNTIME.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
public enum RetentionPolicy {
    /**
     * Only in source code, the compilation phase is discarded and will not be included in the class bytecode file.
     */
    SOURCE,

    /**
     * [Default Policy) exists in the class bytecode file, is discarded when the class is loaded, and is not available at runtime
     */
    CLASS,

    /**
     * It will never be discarded. Reflection can be used to get information about the annotation. Custom annotations are most commonly used.
     */
    RUNTIME
}

3.1.3 @Documented

Indicates whether information about this annotation is added to a javadoc document

3.1.4 @Inherited

Define the relationship between the annotation and the subclass, and use the custom annotation declared by the annotation. When the annotation is used on the class, the subclass will automatically inherit the annotation, otherwise, the subclass will not inherit the annotation. Note that annotations declared with @Inherited are valid only when used on classes, and invalid for methods, attributes, etc.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Person {
    String value() default "man";
}
@Person
public class Parent {
}
//Subclasses also have @Person annotations
class Son extends Parent {

}

3.2 Summary of Definition Annotations

Define annotations with @interface

Multiple parameters can be added, and the core parameter can be assigned a value by convention. Default values can be set for each parameter. The parameter types include basic type, String and enumeration.

Meta-annotations can be used to decorate annotations. Meta-annotations include multiple annotations, and @Target and @Retention must be set, and @Retention is generally set to RUNTIME.

IV. Annotation Processing

As we mentioned earlier, light configuration annotations do not work. It is necessary to implement the logic that the annotations want to express through the corresponding code.

Annotations are defined as a class, and all annotations inherit from java.lang.annotation.Annotation. Therefore, reading annotations requires reflection API.

//Annotations to definitions
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Colum {
    String value() default "";
    //Used to represent the Chinese meaning of an attribute.
    String name() default "";
}

Decorate the attributes of a class with the annotation @Colum

public class Person {

    @Colum(name = "Full name")
    private String name;

    @Colum(name = "Gender")
    private String gender;

    @Colum(name = "Age")
    private int age;

    @Colum(name = "address")
    private String address;

    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public String getGender() {return gender;}
    public void setGender(String gender) {this.gender = gender;}
    public int getAge() {return age;}
    public void setAge(int age) {this.age = age;}
    public String getAddress() {return address;}
    public void setAddress(String address) {this.address = address;}
}

The Chinese meaning of all fields of this class is read by reflection, saved to list, and then printed out.

public static void main(String[] args) throws ClassNotFoundException {
    List<String> columNames = new ArrayList<>();
    Class clazz = Class.forName("annotation.Person");
    //Get all properties of Person class
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields){
        //Colum annotations to get this attribute
        Colum colum = field.getAnnotation(Colum.class);
        //Or you can decide whether there is a comment or not.
        field.isAnnotationPresent(Colum.class);
        //The attribute is extracted from the set of Chinese characters in the collection by annotation.
        columNames.add(colum.name());
    }

    //Print set
    columNames.forEach((columName) -> System.out.println(columName));
}

The results are as follows:

Full name
 Gender
 Age
 address

For example, we have some common application scenarios, we need to export the list on the website into excel tables. We configure the column names by annotation, and then read the values of each field that the entity needs to export (whether it needs to export or can be configured by annotation) by reflection, so as to realize the components exported by excel.

Five. Conclusion

This article just explains the basic concept of annotation, the function of annotation, the function and usage of several meta-annotations, and explains the processing of annotation through a simple example, which is not comprehensive. In this paper, the basic Api of annotation is explained through Field, but annotation can also modify classes, constructors, methods, etc. There are corresponding annotation processing methods, everybody. You can check the relevant content of API manual by yourself. There are many similarities and differences. Please criticize and correct them. We hope to make progress together. Thank you.

Posted by srihari3d2010 on Sat, 05 Oct 2019 07:35:22 -0700