In our work, we sometimes need to encapsulate some common functions, such as operation log storage, anti-double commit, etc. Some of these functions are used by interfaces, but custom annotations are less intrusive to facilitate the use of other interfaces and methods. Just annotate what others are using. Let’s talk about custom annotations.

1.@Target, @Retention, @Documented

Annotations for Java custom annotations are located under the package: java.lang.Annotation. There are three meta-annotations: @target, @Retention, and @Documented.

@Target

@target: The Target of the annotation. And enumeration ElementType

According to the source code, you can configure multiple targets.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
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();
}
Copy the code

The types of ElementType are as follows:

* @author  Joshua Bloch
 * @since 1.5
 * @jls 9.64.1. @Target
 * @jls 4.1 The Kinds of Types and Values
 */
public enum ElementType {
    Class, interface (including annotation type), or enumeration declaration */
    TYPE,
 
    /** Field declarations (including enumeration constants) */
    FIELD,
 
    /** Method declaration */
    METHOD,
 
    /** Formal parameter declaration */
    PARAMETER,
 
    /** The constructor declares */
    CONSTRUCTOR,
 
    /** Local variable declaration */
    LOCAL_VARIABLE,
 
    /** Annotation type declaration */
    ANNOTATION_TYPE,
 
    /** package declaration */
    PACKAGE,
 
    /** * Type parameter declaration **@since1.8 * /
    TYPE_PARAMETER,
 
    /** * The type used **@since1.8 * /
    TYPE_USE
}
Copy the code

@Retention

Indicates how long annotations with annotation types should be retained. If there are no reserved comments and a comment type declaration exists, the default reservation policy is {@code retentionPolicy. CLASS} and RetentionPolicy work together.

The RetentionPolicy types are as follows:

package java.lang.annotation;

/**
 * Annotation retention policy.  The constants of this enumerated type
 * describe the various policies for retaining annotations.  They are used
 * in conjunction with the {@link Retention} meta-annotation type to specify
 * how long annotations are to be retained.
 *
 * @author  Joshua Bloch
 * @since1.5 * /
public enum RetentionPolicy {
    /** * Annotations are only kept in the source file. When a Java file is compiled into a class file, annotations are discarded. Ignored by the compiler */
    SOURCE,

    /** * annotations are kept in the class file, but are discarded when the JVM loads the class file, which is the default lifecycle */
    CLASS,

    /** * annotations are not only saved to the class file, but also exist after the JVM loads the class file
    RUNTIME
}

Copy the code

The three life cycles correspond to: Java source files (.java files) –>.class files –> bytecode in memory.

So how do you choose the right annotation life cycle?

SOURCE < CLASS < RUNTIME = SOURCE < CLASS < RUNTIME = SOURCE < CLASS < RUNTIME Generally, if you need to dynamically retrieve annotation information at RUNTIME, you can only use RUNTIME annotations. Use CLASS annotations if you want to do some pre-processing at compile time, such as generating auxiliary code (such as ButterKnife). If you just do some checking operations, such as @Override and @SuppressWarnings, use the SOURCE annotation.

**@**Documented

**@**Documented Indicates that the annotation should be Documented by the Javadoc tool. By default, Javadoc does not include annotations. However, if @documented is specified when you declare an annotation, it will be processed by a tool like Javadoc, so the annotation type information will also be included in the resulting document as a marker annotation with no members.

Write custom annotations

1. Create a custom annotation package

Of course, the name is custom

2. Create custom annotations

I’m going to use Log as an example. This is created by creating a new custom annotation. You can also manually create a class to modify the @interface.

public @interface test {
}
Copy the code

3. Include meta-annotations

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String value(a) default "";
}
Copy the code

4. Write the AOP

@Aspect
@Component
public class SysLogAspect {

    /** * logger */
    private static final Logger LOGGER = LoggerFactory.getLogger(SysLogAspect.class);


    @Pointcut("@annotation(com.aldeo.common.annotation.Log)")
    public void logPointCut(a) {}@Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // Target method
        Object result = point.proceed();
        long time = System.currentTimeMillis() - beginTime;
      
      Log syslog = method.getAnnotation(Log.class);
        if(syslog ! =null) {
            // The description in the annotation
            LOGGER.info(syslog.value());
        }
      
        // Save the log
        try {
            saveLog(point, time);
        } catch (Exception e) {
            LOGGER.error("==================================> saveSysLog.around.exception: " + e.getMessage(), e);
        }
        return result;
    }
Copy the code

3.

Annotate methods that need annotations

@log (" Test custom annotations ")
public String restPassword(a){
    return "Success";
}
Copy the code

The results

The 2020-11-14 16:09:00. HTTP - nio - 6089-245 | - INFO exec - 9 C.V.T. *. 40 - gmzakixAkym3: test custom annotationsCopy the code

4. Custom annotation usage scenarios and principles

The principle of custom annotations is to define your own annotations. Add annotations to methods that need them. The annotated object is then intercepted in the interceptor, and subsequent processing is performed.

Logging, permission blocking, logging, and various Java frameworks such as Spring, Hibernate, and JUnit mention annotations without reference to reflection. Java custom annotations are obtained by reflection at runtime. In real development, for example, if we want to get the invocation log of a method, we can use AOP (dynamic proxy mechanism) to add facets to the method, use reflection to get annotations contained in the method, and log annotations if they are included. Reflection is implemented at the Java application level through operations on Class objects, which provide a set of methods to operate on classes. From the PERSPECTIVE of the JVM, a Class file is a set of binary streams based on 8-bit bytes, in which data items are arranged in a strict and compact order, containing classes, methods, fields, and other related data. By processing the Class data stream, we can get fields, methods, and so on.