【五】Annotation

1. Concept

Annotation Annotation is a new feature of Java 1.5, a kind of grammatical metadata that can be added to Java source code. Classes, methods, variables, parameters, and packages can all be annotated and can be used to associate information metadata with program elements. Annotation is often translated as "Note" in Chinese.

2. Function

  1. Marker, used to tell the compiler some information
  2. Dynamic processing at compile time, such as dynamically generating code
  3. Dynamic processing at runtime, such as getting annotation information

Java annotations can be used during construction. When building our project, the build process will compile the source code, generate an xml file, and package the compiled code and files into a jar package. The build process is generally completed automatically by build tools, and commonly used build tools are ant and maven. The build tool will automatically scan our code when building, and when it encounters a build period annotation, it will generate source code or other files based on the content of the annotation

3. The format of annotations

  1. A java annotation consists of an @ sign followed by a string
@Entity
  1. Java annotations generally contain some elements, these elements are similar to attributes or parameters, which can be used to set values
@Entity(userName = “zphuan”, userAge =100)

There are two elements in this annotation: userName and userAge, which are assigned corresponding element values.

4. The position of the annotation

1. The position of the annotation

Annotations can be used to describe a class, interface, method, method parameter, field, etc.

	@Author(
	   name = "zphuan",
	   date = "3/24/2017"
	)
	class MyClass() {
    
    
        
        @Value
        String name;
        
        @Override
        void mySuperMethod(@RequestParam String name) {
    
    
        }
    }

2. Details of use

1. There is no need to write the parameter body if there is no parameter, such as @Override

2. If there is only one parameter such as named value, the parameter name can be omitted, such as:

	@SuppressWarnings("unchecked")
	void myMethod() {
    
     ... }

3. You can also use multiple annotations to mark at the same time, such as:

	@Author(name = "Jane Doe")
	@EBook
	class MyClass {
    
     ... }

4. Annotations can be reused, but only supported in java SE 8. such as:

	@Author(name = "Jane Doe")
	@Author(name = "John Smith")
	class MyClass {
    
     ... }

Indicate the writing of the category by two authors, one administrator, one developer, etc.

  • Note: If you want to customize an annotation that can be used repeatedly (custom annotations will be covered later), remember to add @Repeatable, such as:
	@Repeatable(Authors.class)
	public @interface Author {
    
    
      String name() default "";
	  String value() default "";
	}

	public @interface Authors {
    
    
	  Author[] value() default {
    
    };
	}

5.Annotation architecture

Annotation is an interface with many implementation classes, including: Deprecated, Documented, Inherited, Override, etc.

When using @interface to define an annotation, it means that it implements the java.lang.annotation.Annotation interface, that is, the annotation is an Annotation.

Note: It is different from our usual implemented interface method. The implementation details of the Annotation interface are all done by the compiler. After defining an annotation through @interface, the annotation cannot inherit other annotations or interfaces.

package java.lang.annotation;
public interface Annotation {
    
    

    boolean equals(Object obj);

    int hashCode();

    String toString();

    Class<? extends Annotation> annotationType();
}

img

6.Java built-in annotations

Java itself provides three built-in annotations, they are: @Deprecated, @Override, @SuppressWarnings, package pathjava.lang

1.@Deprecated

It can be used to describe a class, method or field, which means that Java does not approve the use of these described objects. If we use these classes, methods or fields, the compiler will warn us.

2.@Override

Annotation is a compile-time annotation, which is mainly used in a method of a subclass. When the method of the annotated subclass cannot find a matching method in the parent class, the compiler will report an error.

3.@SuppressWarnings

The function of the annotation is to make the compiler ignore the compiler warning. For example, if one of our methods calls an @Deprecated method, or makes an unsafe type conversion, the compiler will generate a warning. If we don't want to see these warnings, we can use the @SuppressWarnings annotation to ignore these warnings.

7. Meta annotations

Meta-annotation is the annotation used to describe the annotation, the package pathjava.lang.annotation

1.@Documented

The function is to tell the JavaDoc tool that the current annotation itself should also be displayed in the Java Doc. For example, the custom annotation I wrote above.

2.@Retention

Used to define the scope of the current annotation

package java.lang.annotation;
// 这3个生命周期分别对应于:Java源文件(.java文件) ---> .class文件 ---> 内存中的字节码
// 生命周期长度 SOURCE < CLASS < RUNTIME
public enum RetentionPolicy {
    
    
    SOURCE,            /* 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃  */

    CLASS,             /* 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期  */

    RUNTIME            /* 编译器将Annotation存储于class文件中,并且可由JVM读入,在运行期有效,JVM在运行期通过反射获得注解信息 */
}

Each implementation class of Annotation is associated with 1 RetentionPolicy

@Retention(RetentionPolicy.RUNTIME)   

3.@Target

It is used to specify which elements of the annotation are applied to java. Unmarked means that all can be modified. There are the following element types to choose from:

package java.lang.annotation;

public enum ElementType {
    
    
    TYPE,               /* 类、接口(包括注释类型)或枚举声明  */

    FIELD,              /* 字段声明(包括枚举常量)  */

    METHOD,             /* 方法声明  */

    PARAMETER,          /* 参数声明  */

    CONSTRUCTOR,        /* 构造方法声明  */

    LOCAL_VARIABLE,     /* 局部变量声明  */

    ANNOTATION_TYPE,    /* 元注解类型,只能用来注解其它的注解,例如@Target和@Retention  */

    PACKAGE             /* 包声明  */
}

Each implementation class of Annotation is associated with 1~n ElementType.

// 作用范围:字段、枚举的常量、方法
@Target(value={
    
    ElementType.FIELD,ElementType.METHOD}) 

4.@Inherited

Annotation means that the current annotation will be inherited by subclasses of the annotation class. For example, there is a custom annotation:

	@Inherited
	public @interface InheritedAnnotation{
    
    
		
	}

If a class uses the above annotation, then the subclasses of Generation3List will also inherit this annotation.

	@InheritedAnnotation
	public class Generation3List {
    
    
	}

8. Custom annotations

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
    
    
    String value() default "";
}

The @interface keyword means that this is an annotation type, so you can use the @interface keyword to create an annotation.

The definition of each element in the annotation is similar to the method definition in the interface. Each element definition contains a data type and name. The data type of the annotation element can be java basic data type, String, array, but cannot be a complex object type.

We can use the default keyword to set a default value for an element. When an element is set to a default value, this element becomes an optional element for annotations.

    @MyAnnotation1("xxx")
    public class Generation3List{
    
    

	}

8.Annotation analysis

1. Annotation analysis at runtime@Retention(RetentionPolicy.RUNTIME)

1. Get runtime annotations

You need to obtain runtime annotations through reflection, which can be obtained from Package, Class, Field, Method... The basic methods are the same, and several common methods are as follows:

/**
 * 获取指定类型的注解
 */
public <A extends Annotation> A getAnnotation(Class<A> annotationType);

/**
 * 获取所有注解,如果有的话
 */
public Annotation[] getAnnotations();

/**
 * 获取所有注解,忽略继承的注解
 */
public Annotation[] getDeclaredAnnotations();

/**
 * 指定注解是否存在该元素上,如果有则返回true,否则false
 */
public boolean isAnnotationPresent(Class<? extends Annotation> annotationType);

/**
 * 获取Method中参数的所有注解
 */
public Annotation[][] getParameterAnnotations();

To use these functions, you must first obtain the corresponding elements through reflection: Class, Field, Method, etc.

2.@Target(value = { ElementType.TYPE})

@InheritedAnnotation
@ClassPreamble(
    author = "zphuan",
    date = "3/17/2002",
    currentRevision = 6,
    lastModified = "4/12/2004",
    lastModifiedBy = "Jane Doe",
    // Note array notation
    reviewers = {
    
    "Alice", "Bob", "Cindy"}
)
public class Generation3List {
    
    
}
	import com.zphuan.MyAnnotation.ClassPreamble;

	public class Main {
    
    
		public static void main(String[] args) {
    
    
			//通过反射获得Generation3List的注解信息
			ClassPreamble preamble = (ClassPreamble) Generation3List.class.getAnnotation(ClassPreamble.class);
			System.out.println("preamble author:"+preamble.author());
		}
	}

3.@Target(value = { ElementType.METHOD })

	@Retention(RetentionPolicy.RUNTIME)
	@Target(value = {
    
     ElementType.METHOD })
	public @interface MethodAnnotation{
    
    
		String author();
		String date();
	}

This annotation works with the test method in the following class:

	public class Generation3List {
    
    
		
		@MethodAnnotation(author = "zphuan", date = "3/26/2017")
		public void test(){
    
    
		}
	}

Now I want to get the annotation information on the method, which can be obtained by reflection like this:

	try {
    
    
		Class clazz = Class.forName("com.zphuan.Generation3List");
		for(Method method : clazz.getMethods()){
    
    
			MethodAnnotation methodAnnotation = method.getAnnotation(MethodAnnotation.class);
			if(methodAnnotation!=null){
    
    
				System.out.println("author:"+methodAnnotation.author());
			}
		}
	} catch (ClassNotFoundException e) {
    
    
		e.printStackTrace();
	}

2. Annotation analysis at compile time@Retention(RetentionPolicy.CLASS)

1. Create an Annotation whose annotation type is CLASS, as follows:

	@Retention(RetentionPolicy.CLASS)
	public @interface ClassAnnotation{
    
    
		String author();
	}
	@ClassAnnotation(author = "zphuan")
	public class Generation3List {
    
    
		
		@MethodAnnotation(author = "zphuan", date = "3/26/2017")
		public void test(){
    
    
		}
	}

2. @Retention(RetentionPolicy.CLASS), automatically parsed by the compiler

The compiler automatically finds all classes inherited from AbstractProcessor at compile time, and then calls their process method to process

import java.util.HashMap;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;

import com.zphuan.MyAnnotation.ClassAnnotation;
/**
 * 1.自定义类继承自 AbstractProcessor
 *  @SupportedAnnotationTypes的值为当前类支持的注解的完整类路径,支持通配符。表示这个 Processor 要处理的 Annotation 名字.
 *  @SupportedSourceVersion 标识该处理器支持的源码版本
 */

@SupportedAnnotationTypes({
    
     "com.zphuan.MyAnnotation.ClassAnnotation" })
public class ClassProcessor extends AbstractProcessor {
    
    

	private static HashMap<String, String> map;

    /**
     * 2.重写其中的 process 函数
     *  annotations 表示待处理的 Annotations
     *  env 表示当前或是之前的运行环境
     *  process 函数返回值表示这组annotations是否被这个Processor接受,如果接受后续子的rocessor不会再对这个Annotations进行处理
     */
	@Override
	public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    
    
		map = new HashMap<String, String>();
		for (TypeElement te : annotations) {
    
    
			for (Element element : roundEnv.getElementsAnnotatedWith(te)) {
    
    
				ClassAnnotation classAnnotation = element.getAnnotation(ClassAnnotation.class);
				map.put(element.getEnclosingElement().toString(), classAnnotation.author());
			}
		}
		return false;
	}
}

9. The role of Annotation

Annotation is an auxiliary class, which is widely used in tool frameworks such as Junit, Struts, and Spring.

1. Compile check

Annotation has the function of "letting the compiler to check the compilation".

For example, @SuppressWarnings, @Deprecated and @Override all have a compilation check function.

If a method is annotated by @Override, it means that the method will override the method of the same name in the parent class. If a method is marked by @Override, but there is no method with the same name "marked by @Override" in the parent class, the compiler will report an error.

2. Use Annotation in reflection

3. Generate help documents based on Annotation

By adding the @Documented tag to the Annotation annotation, the Annotation tag can appear in the javadoc.

4. Custom Annotation to achieve some functions

Generally used with AOP to complete business functions

10. Annotation execution order

In the same package, according to the loading order of the annotation classes (sorted by the class name string), it has nothing to do with the order in which the annotations are used

When two advices defined in different aspects need to run on the same Join Point, unless the order is specifically specified, their execution order is uncertain.

Spring AOP follows the same priority rules as AspectJ to determine the order of execution of recommendations.

The priority can be controlled by @Order, the smaller the number, the higher the priority. When it comes in, the Advice with the highest priority runs first, and when it goes out, the Advice with the highest priority runs last.

@Target({
    
    ElementType.Method})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAnnotation1{
    
    
    
}
@Target({
    
    ElementType.Method})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAnnotation2{
    
    
    
}

@Slf4j
@Aspect
@Order(1)  
public class AopAspect1{
    
      
    
    @Around("@annotation(com.dyn.util.annotation.TestAnnotation1)")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
    
    
        log.info("TestAnnotation1被加载");
        return pjp.proceed();
    }

}
@Slf4j
@Aspect
@Order(2)  
public class AopAspect2{
    
      
    @Around("@annotation(com.dyn.util.annotation.TestAnnotation2)")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
    
    
        log.info("TestAnnotation2被加载");
        return pjp.proceed();
    }
}

@RestController
public class Controller{
    
    
    
    @TestAnnotation1
    @TestAnnotation2
    @TestAnnotation10
    @TestAnnotation01
    @TestAnnotation0
    @RequestMapping(value="/test",method=RequestMethod.POST)
    public void test(){
    
    
        
    }
}
MyAnnotation0 > MyAnnotation01  > MyAnnotation1 > MyAnnotation10 > MyAnnotation2

11. Annotation conflicts

Reasonable selection of annotations according to business scenarios to avoid conflicts

Guess you like

Origin blog.csdn.net/qq_25046005/article/details/112987372