One, foreword

This is the sixth day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021. I’ve heard of people who can’t customize annotations? Can’t write and can’t Copy? ☞ Secondary packaging, annotation driven, use not too comfortable! – Juejin (cn), no more joking. today, we will take you to sort out the annotation, that is, the correct way to open @interface. In addition, we can print the entry and exit log with the AOP aspect, so that every request to access the annotation binding interface method can be clearly seen. Not only is the interface easy to debug, but it also gives you an elegant, neat and generous console logging.

Second, the effect demonstration

2.1 Access Interface

2.2 Console Log Output

How to design a note

3.1 concept

Know what it is, know why it is, so let’s first come to kangkang’s official description of annotations:

An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.

Translation:

Annotations are a form of metadata that can be added to Java source code. Classes, methods, variables, parameters, and packages can be annotated. Comments have no direct effect on the operation of the code they annotate.

In summary, annotations are a special type of data in Java, and can also be thought of as a customizable tag. Like classes, interfaces, and enumerations, annotations can be used in many different ways and have no effect on the original operation code, only for intermediate collection and processing.

3.2


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {

    public String name(a);
    
    int sort(a) default Integer.MAX_VALUE; . . }Copy the code

Instructions (from top to bottom) :

  • Using this annotation is retained by the JVM while the program is running and recorded by the compiler in a class file, so properties in the annotation can be read via Java reflection, etc

  • This annotation can only be used on fields, not classes, methods, or variables

  • This annotation has two properties, one is name and one is sort property, property? You might be asking, well, shouldn’t it be a method with parentheses? The annotation type elements are officially defined in annotations, but I prefer to call them attributes because when using annotations, they are always passed as key-value pairs

  • The access modifier must be public. Default to public is not written

  • Parentheses are not the place to define method arguments, and you cannot define any arguments within parentheses; this is just a special notation

  • Default indicates the default value when the attribute is not set. The value must be consistent with the type

  • If there is no default value, the element of the type must be assigned later

3.3 Annotation annotation class

In addition, the JDK provides four standard annotation classes (meta-annotation) for annotating annotation types:

  • @TargetIs specifically used to define where a custom annotation can be appliedJavaOn the element

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    /** class, interface (including annotation type) or enumeration declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    /** Field declarations (including enumeration constants) */
    FIELD,

    /** Method declaration */
    /** method declaration */
    METHOD,

    /** Formal parameter declaration */
    /** the parameter declares */
    PARAMETER,

    /** Constructor declaration */
    /** The constructor declares */
    CONSTRUCTOR,

    /** Local variable declaration */
    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    /** package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since1.8 * /
    /** Type parameter declaration */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since1.8 * /
    /** Use type */
    TYPE_USE
}
Copy the code
  • @RetentionThis note is used to define the retention strategy of the note. Only the retention strategy can be specified3A:

public enum RetentionPolicy {
    /** * Annotations are to be discarded by the compiler
    SOURCE,

    /** * Annotations are to be recorded in the class file by the compiler * but need not be retained by the VM at run time. This is the default * behavior. * * Comments are recorded by the compiler in the class file, but do not need to be retained by the virtual machine at runtime. This is a default behavior. * /
    CLASS,

    /** * Annotations are to be recorded in the class file by the compiler and * retained by the VM at run time, So they may be read reflectively. * * Comments will be recorded in class files by the compiler and retained by the virtual machine at run time, so they can be read by reflection. * *@see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
Copy the code

For general use, there is no special need to use retentionPolicy.runtime.

  • Documented is used to specify whether a custom annotation will be generated into a JavaDoc document along with the defined Java file

  • @Inherited specifies a custom annotation. When Inherited is written in the declaration part of the parent, the declaration part of the child class automatically owns the annotation

Note:@InheritedNotes are only for those@TargetIs defined asElementType.TYPECustom annotations of the.

3.4 Usage Process

Four, code implementation

4.1 the first step

Write design notes:


/ * * *@description: TODO
 * @author: HUALEI
 * @date: 2021-11-19
 * @time: now * /
@Retention(RetentionPolicy.RUNTIME)
/* The annotation is used in the method */
@Target(ElementType.METHOD)
public @interface MyAnnotation {

    /** * interface method description */
    public String description(a) default"Default description";
}
Copy the code

This step is nothing to talk about, the above concept of understanding, easy to write this note should be no problem!

4.2 the second step

Use a section annotation to mark it. Since we are printing request-specific logs, let’s write a random control-layer interface method to test it:


/ * * *@description: TODO
 * @author: HUALEI
 * @date: 2021-11-24
 * @time: shine forth * /
@RestController
@RequestMapping(value = "/test")
public class TestController {

    private final static Logger log = LoggerFactory.getLogger(TestController.class);

    @GetMapping("/hello/{say}")
    @myAnnotation (description = "test interface ")
    public String sayHello(@PathVariable("say") String content) {
        log.info("Client is saying: {}", content);
        returncontent; }}Copy the code

4.3 the third step

The last and most critical step is to parse annotations to perform the aspect operation at runtime, so write a corresponding aspect class:

After creating the section class, this code is essential for logging printing:


/ * * *@description: TODO
 * @author: HUALEI
 * @date: 2021-11-19
 * @time: 15:56 * /
@Aspect
@Component
public class MyAnnotationAspect {

    private static finalLogger logger = LoggerFactory.getLogger(MyAnnotationAspect.class); . . }Copy the code

The @aspect and @Component annotations are essential, and @Component should be familiar enough to inject into the Spring container; The other @aspect annotation identifies the current class as a section for the container to read.

Note: The recommended package to print logs is slf4j.logger.


/** * configures the weave point ** to cut to all be@MyAnnotationAnnotation methods */
@Pointcut("@annotation(com.xxx.xxx.annotation.MyAnnotation)")
// @annotation(annotationType) matches methods that specify annotations as pointcuts, with annotationType being the full path of annotations
public void myAnnotationPointCut(a) {}Copy the code

Configure the texture point, cut to all methods decorated with the @MyAnnotation annotation, no need to write actual code inside the method!


/** * Wrap enhancement, customizable timing of target method execution * implementation records all files@MyAnnotationAnnotations modify interface request functionality * *@paramPJP join point object *@returnThe return value of the target method *@throwsThrowable exception * /
@Around("myAnnotationPointCut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
    // Request start timestamp
    // long begin = System.currentTimeMillis();

    TimeInterval timer = DateUtil.timer();

    // Through the request context (before the target method is executed)
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

    HttpServletRequest request = attributes.getRequest();

    // Get the method signature object for the join point
    Signature signature = pjp.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;

    // Get the interface method
    Method method = methodSignature.getMethod();
    // Get the @myAnnotation object on that method via the interface method
    MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);

    // Get the interface method description via annotations
    String description = myAnnotation.description();

    // Start request (pre-notification)
    logger.info("> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > request to < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <");
    // Request a link
    logger.info("Request link: {}", request.getRequestURL().toString());
    // Interface method description
    logger.info(Interface Description: {}, description);
    // Request type
    logger.info("Request type: {}", request.getMethod());
    // Request method
    logger.info("Request method: {}.{}", signature.getDeclaringTypeName(), signature.getName());
    // Request remote address
    logger.info("Request remote address: {}", request.getRemoteAddr());
    // Request an input parameter
    logger.info("Request entry: {}", JSONUtil.toJsonStr(pjp.getArgs()));

    // Request end time stamp
    // long end = System.currentTimeMillis();

    // Request time
    logger.info(Request Time: {}, timer.intervalPretty());

    // Request return result (after executing target method)
    Object processedResult = pjp.proceed();
    // The request is returned
    logger.info("Request return: {}", JSONUtil.toJsonStr(processedResult));

    // End of request (post notification)
    logger.info("> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > request end < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <" + System.lineSeparator());

    return processedResult;
}
Copy the code

The PJP JoinPoint object, a subinterface of JoinPoint, can get the parameters of the current method, the proxy class, etc., so it can record some information, verify some information, etc. It has two important methods:

  • Object Proceed () throws Throwable Executes the target method

  • Object proceed(Object[] var1) throws Throwable with new arguments passed to execute the target method

The entire code is annotated, so there is no need to talk about the code logic here!

4.4 extensions

In addition to the @pointcut and @around annotations used above, there are four other annotations commonly used with AOP:

  • @before: Pre-enhanced to weave in the relevant code Before the pointcut

  • @after: Final enhancement, whether an exception is thrown or a normal exit

  • @afterreturning: Post-enhanced, executed when the method exits normally

  • AfterThrowing: Exception throwing enhancement, executed when a pointcut method throws an exception

Order of execution: @around => @before => Execute code in interface methods => @after => @afterreturning

Interested students can wrap around the code in the enhancement and split it into pre – and post-annotations to better understand the four common annotation usage scenarios! (๑ • ̀ ㅂ ́) organisation ✧

At the end

Writing is not easy, welcome everyone to like, comment, your attention, like is my unremitting power, thank you to see here! Peace and Love.