Principle analysis of java annotation

1, Meta annotation

1. @ target (action target)

Scope of annotation
typeexplain
ElementType.TYPEClass, interface (including annotation type) or enum declaration
ElementType.FIELDFields, enumerating constants
ElementType.METHODMethod declaration
ElementType.PARAMETERParameter declaration
ElementType.CONSTRUCTORConstructor declaration
ElementType.LOCAL_VARIABLELocal variable declaration
ElementType.PACKAGEPackage declaration
ElementType.LOCAL_VARIABLElocal variable
ElementType.ANNOTATION_TYPEannotation

2. @ retention (retention policy)

Indicates the level at which the annotation information is saved
typeexplain
RetentionPolicy.SOURCEAnnotations exist only in the source code and are not included in the class bytecode file
RetentionPolicy.CLASSWith the default retention policy, annotations exist in the class bytecode file, but cannot be obtained at run time
RetentionPolicy.RUNTIMEAnnotations exist in the CLASS bytecode file and can be obtained by reflection at RUNTIME. First, specify the life cycle length SOURCE < CLASS < RUNTIME, so where the former can work, the latter must also work. Generally, if you need to dynamically obtain annotation information at RUNTIME, you can only use RUNTIME annotation; If you want to perform some preprocessing operations during compilation, such as generating some auxiliary code (such as ButterKnife), use CLASS annotation; If you only do some checking operations, such as @ Override and @ SuppressWarnings, you can use the SOURCE annotation.

3,@Documented

Include this annotation in javadoc, which means that this annotation will be extracted into documents by javadoc tools. The content in the doc document will vary according to the information content of this annotation. Equivalent to @ see,@param, etc.

4,@Inherited

Inherited means inheritance, but it does not mean that it can be inherited directly, but that a superclass is annotated by @ Inheritedh,

2, Reflection

The reason why reflection is explained here is that annotation and reflection are closely related. Without reflection, the annotation function cannot be parsed.

1. Concept

class
Method
Field
Constructor

2. Reflection core class

java.lang.Class;     class
java.lang.reflect.Constructor;    Constructor method
java.lang.reflect.Field;    attribute
java.lang.reflect.Method;    method
java.lang.reflect.Modifier;    Modifier 

3. Class loading has three stages

1,source code(source)
    The original code does not refer to java File, yes class Bytecode file
2,Class loading(class)
    class Bytecode file via classloader classloader Load into the virtual machine memory, and the class loader resolves class File generation Class Object of type
3,Runtime(runtime)
    newInstance()according to java Type generation object

4. Three methods to get class objects

1,Class class=Class.forName("com.xx.xx.xx.Person");
2,Class<Person> class=Person.class;
3,Person p=new Person();
   Class class=p.getClass();

3, Parsing annotation (source code analysis)

Write an annotation, customize and return your own toString method. Return the format you want

The complete code can be viewed under this project cloud-annotation

1. Create custom annotation

Annotation namefunction
@JsonFormatFormatting function
@JsonIgnoreIgnore function
@JsonPropertyAttribute name
/**
 * Acts on the attribute, and the user formats the date as required
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface JsonFormat {
    String pattern() default "yyyy-MM-dd HH:mm:ss";
}
/**
 * Acts on attributes to ignore some attributes
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface JsonIgnore {
}
/**
* property alias 
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface JsonProperty {
    String value(); //Value must be given when using

2. After the annotation is defined, customize the tojsonstring (similar to toString) method

package com.xwb.springcloud.annotation.json;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;

@SuppressWarnings("all")
public class JSON {
    public static String toJSONString(Object object) {
        StringBuffer json = new StringBuffer();
        try {
            //1. Get the Class object of object
            Class<?> clazz = object.getClass();
            //2. Get all the attributes in class
            Field[] fields = clazz.getDeclaredFields();
            //3. Loop through all attributes to break the access rights of attributes
            int index = 0;
            //Get attribute length
            int length = fields.length;
            json.append("{");
            for (Field field : fields) {
                index++;
                //Judge whether there are ignored annotations on the attribute
                if (field.isAnnotationPresent(JsonIgnore.class)) {
                    continue;
                }
                //Private variable readability
                field.setAccessible(true);
                //4 get the attribute name as the key of json
                String name = field.getName();
                //5. Get the attribute value as the json value
                Object value = field.get(object);
                //Judge whether there is a comment to change the name on the attribute
                if (field.isAnnotationPresent(JsonProperty.class)) {
                    //If so, take out the name on the annotation
                    JsonProperty annotation = field.getAnnotation(JsonProperty.class);
                    name = annotation.value();
                }
                json.append("\"" + name + "\"");
                if (value instanceof String) {
                    json.append(":\"" + value.toString() + "\"");
                } else if (value instanceof Date) {
                    //If it is a date here, judge whether there is a comment formatted from the date
                    Date date = (Date) value;
                    if (field.isAnnotationPresent(JsonFormat.class)) {
                        JsonFormat format = field.getAnnotation(JsonFormat.class);
                        json.append(":\"" + parseDateToStr(date, format.pattern()) + "\"");
                    } else {
                        json.append(":\"" + date.getTime() + "\"");
                    }
                } else {
                    json.append(":" + value.toString());
                }
                if (index != length) {
                    json.append(",");
                }
            }
            json.append("}");
            return json.toString();
        } catch (Exception e) {
            System.out.println(e.getCause());
        }
        return null;
    }
    public static String parseDateToStr(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }
}

explain:

The defined annotation has no effect, but if you want the annotation to play its role, you need to define corresponding methods to parse it, and then let it play its role.
Who defines the annotation, who parses it. Instead of saying that the annotations defined by him let java parse them, he doesn't recognize them.

3. Call

public class TestJSON {
    public static void main(String[] args) {
        User user = new User(1, "Zhang San", "Yinchuan, Ningxia", new Date());
        String s = JSON.toJSONString(user);
        System.out.println(s);
    }
}

4. Output results

{"user_name": "Zhang San", "user_address": "Yinchuan, Ningxia", "birth": "2021-11-12"}

Example

Summary: the annotation itself has no function, it is just a statement. The specific function is to define what function the annotation developer wants it to play, and then use reflection in the corresponding parsing method to obtain whether there is the annotation on classes, attributes, methods, parameters... And if so (xxx instanceof xxx) to implement the function method according to the developer's own ideas.
The shortcut key used to find the class or method in the source code is [ctrl+n]

1. spring @ RequestBody annotation

Resolve the RequestResponseBodyMethodProcessor class under the package spring-webmvc-5.2.2.RELEASE.jar
For a detailed description of this annotation, please watch this blog @RequestBody

2. mybatis @ Mapper annotation

MapperAnnotationBuilder class parse method RequestResponseBodyMethodProcessor under mybatis-3.4.4.jar package
See this blog for @ Mapper @Mapper

3. spring @ Configuration

ConfigurationClassPostProcessor class under spring-context-5.2.2.RELEASE.jar package
For detailed explanation of the source code, you can view the blogger's blog @Configuration

4. @ FeignClient annotation for springcloud

Feignclientsregister class of spring-cloud-openfeign-core-2.2.1.RELEASE.jar package
For the source code analysis of @ FeignClient, please see this blog @FeignClient

Keywords: Java Back-end

Added by j_smith123 on Fri, 12 Nov 2021 11:56:57 +0200