Java customizes the Annotation and parses the Annotation through reflection

Keywords: Java source code analysis annotations

1, Introduction

For those who have used Spring, annotations are no stranger. I have also written an article to introduce annotations before.

https://blog.csdn.net/zxd1435513775/article/details/89973721

2, Custom annotation

1. Create a custom Annotation

@Documented
@Target(ElementType.METHOD) // Indicates that the annotation can only be used to decorate methods
@Retention(RetentionPolicy.RUNTIME)	// The annotation will be valid at run time (i.e. retained at run time)
public @interface MethodInfo {
	// The following are attribute methods
    String author() default "dada";
    String version() default "1.0";
    String date();
    String comment();
}
  • @Target function: used to describe the scope of use of annotations (i.e. where the described annotations can be used)

    @Target describes the object scope modified by Annotation: Annotation can be used for packages, types (classes, interfaces, enumerations, Annotation types), type members (methods, construction methods, member variables, values), method parameters and local variables (such as loop variables and catch parameters). Target is used in the declaration of Annotation type to clarify the target it modifies.

@The Target values (ElementType) are:

1.CONSTRUCTOR: used to describe the constructor
2.FIELD: used to describe the field
‚Äč 3.LOCAL_VARIABLE: used to describe local variables
4.METHOD: used to describe the method
5.PACKAGE: used to describe the package
6.PARAMETER: used to describe parameters
7.TYPE: used to describe class, interface (including annotation type) or enum declaration

  • @Retention function: indicates the level at which the annotation information needs to be saved, which is used to describe the annotation life cycle (i.e. to what extent the described annotation is valid)

    @Retention defines how long the Annotation is retained: some annotations only appear in the source code. When the source code is compiled by the compiler, these annotations will be discarded by the compiler and will not appear in the class file; Some can be compiled into class files; Annotations compiled in the class file may be ignored by the virtual machine, while others will be read when the class is loaded (please note that it does not affect the execution of the class, because Annotation and class are separated in use). Use this meta Annotation to limit the "life cycle" of an Annotation.

@The Retention policy values include:

1.SOURCE: valid in source file (i.e. source file retention)
2.CLASS: valid in class file (i.e. class reserved)
3.RUNTIME: valid at runtime (i.e. reserved at runtime)

  • @Documented

    @Documented is used to describe that other types of annotations should be used as a public API for annotated program members, so they can be documented by tools such as javadoc. Documented is a tag annotation with no members.

  • @Inherited:

    @Inherited meta annotation is a tag annotation, @ inherited describes that a marked type is inherited. Then this annotation will be used for subclasses of the class.

Note: @ Inherited annotation type is inherited by the subclass of the marked class. Class does not inherit annotation from the interface it implements, and methods do not inherit annotation from the methods it overloads.

2. Java built-in Annotation

Starting with the Java 5 version, there are three standard annotation types.

Override, java.lang.Override is a marker annotation type, which is used as a annotation method. It shows that the marked method overloads the method of the parent class and plays the role of assertion. If we use this annotation, the java compiler will warn us of a compilation error when a method does not override the parent method. This annotation often adds a guaranteed verification process when we try to override the parent method and write the wrong method name.

Deprecated is also a marker annotation. The compiler will not encourage the use of this annotated program element. Therefore, using this modification has a certain "continuity": if we use this obsolete type or member in the code by inheritance or override, although the inherited or overridden type or member is not declared @ deprecated, the compiler still needs to alarm. Note: the @ deprecated annotation type is different from the @ deprecated tag in javadoc: the former is recognized by the java compiler, while the latter is recognized by the javadoc tool to generate documents.

SuppressWarnings, which tells the Java compiler to turn off warnings for classes, methods, and member variables. Sometimes some warnings will be raised during compilation. Some of these warnings hide bugs and some are unavoidable. For some unwanted warning messages, you can mask them through this annotation. SuppressWarning is not a marker annotation. It has a member of type String [] whose value is the prohibited warning name. For the javac compiler, the compiler also ignores unrecognized warning names.

Let's use Java's built-in Annotation and custom Annotation

public class AnnotationExample {
    @Override
    @MethodInfo(author = "scorpios",version = "1.0",date = "2019/10/20",comment = "aaaa")
    public String toString() {
        return "AnnotationExample{}";
    }
}

Use reflection to resolve annotations

Note: the Retention Policy of Annotation must be RUNTIME, otherwise we cannot get any data from this class at RUNTIME

public class AnnotationParser {

    public static void main(String[] args) {
        // Get all the methods in the class and loop through each method
        for (Method method: AnnotationExample.class.getMethods()) {
            // Judge whether the method is annotated with MethodInfo annotation
            if (method.isAnnotationPresent(MethodInfo.class)) {
                // Get the annotation information and traverse the data in the annotation
                for (Annotation annotation:method.getAnnotations()) {
                    System.out.println("------------------------");
                    System.out.println(annotation + " works on method:"+ method);
                }

                MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);

                System.out.println(methodInfo);
                System.out.println(methodInfo.author());
                System.out.println(methodInfo.comment());
                System.out.println(methodInfo.date());
                System.out.println(methodInfo.version());

            }
        }
		System.out.println("--------------Reflection call method---------------");
        try {
            AnnotationExample example = new AnnotationExample();
            Class clazz = example.getClass();
            Method method = clazz.getDeclaredMethod("toString");

            String result = (String) method.invoke(example);
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

Output results:

3, Automatically generate query SQL using custom annotations

@Entity("city")
public class City {

    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class CommonUtil {

    public static String buildQuerySqlForEntity(Object object){

        String sql = "select * from ";

        Class clazz = object.getClass();
        // Judge whether there are notes
        if(clazz.isAnnotationPresent(Entity.class)){
            // Get comments
            Entity entity = (Entity) clazz.getAnnotation(Entity.class);
            // Call property method
            String value = entity.value();
            sql = sql + value;
        }
        return sql;
    }
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
    public String value() default "";
}
public static void main( String[] args ) {
    City city = new City();
    city.setId(1);
    city.setName("nanjing");
    String sql = CommonUtil.buildQuerySqlForEntity(city);
    System.out.println(sql);
}

Posted by pfchin on Sat, 09 Oct 2021 18:42:48 -0700