SpringMVC’s custom annotations (this blog will show you the charm of custom annotations)

Table of contents

Edit

Preface

1. Introduction to Java annotations

1. What are Java annotations?

2. Java annotation classification

2.1 JDK basic annotations

2.2 JDK meta-annotations

Note:

 2.3 Custom annotations

Case:

2. Custom annotations (used in SpringMVC)

Case explanation

Case 1: (Getting annotation values ​​on classes and methods)

Deployment test (define three constants)

Define and write three custom label classes

Custom label 01 (MyAnnotation1.java)

Custom label 02 (MyAnnotation2.java)

Custom label 03 (MyAnnotation3.java)

Related test categories

Demo1.java

Demo1Test

Test Results

list() method test results

 edit() method test results

Case 2: (Get the annotation attribute value on the class attribute)

Custom label class written

Test Case

Test paper code

Test Results

test()02 test results

test()03 test results

test()04 test results

Case 3; (Get the attribute value corresponding to the parameter modification annotation)

Custom label class written

 Test Case

Test paper code

Test Results

hello1() method test results

hello2() method test results 

hello3() method test results 

hello1() method test result (name attribute is empty) 

3. Aop custom annotation case (key points)

Test Case

MyLog.java

Section type

MyLogAspect.java

Controller class

LogController.java

Test Results

Situation one:


Preface

        Hello fellow veterans, those who have read my previous blogs all know that in previous blog sharings we learned about JSON return types, exception handling mechanisms, JSR303, interceptors, etc. Today I will take you all to explore a new field - custom annotations .

1. Introduction to Java annotations

1. What are Java annotations?

        Java annotations are a special syntax element of the Java language that can be used to add additional metadata information to the code. Annotations can be used on various program elements such as classes, methods, variables, parameters, etc. The role of annotations is to provide additional information to other parts of the program so that the compiler, parser, or runtime environment can perform corresponding processing based on the annotation information when processing these program elements.

        Java annotations usually use custom annotations or built-in predefined annotations , such as @Override, @Deprecatedetc. You can also customize annotations as needed.

        The advantage of using Java annotations is that you can add more semantic information to the code through annotations, improving the readability and maintainability of the code . Annotations can also be used to implement the functions of some frameworks, libraries or tools, such as JUnit testing framework, Spring framework, etc.

2. Java annotation classification

2.1 JDK basic annotations

        Some basic annotations provided by the JDK provide compiler-level information and guidance, which can help developers write more accurate and efficient code.

JDK basic annotations
annotation Annotation description
@Override Used to annotate methods, indicating that the method overrides the parent class's method . @OverrideThe compiler will give a warning when a method is marked with an annotation but does not actually override the parent class method.
@Deprecated Used to mark obsolete methods, classes, fields, etc. Indicates that this item is deprecated and may be removed or replaced in future versions.
@SuppressWarnings Used to suppress certain warnings and can be applied to classes, methods, variables, etc. This annotation can accept one or more parameters that specify the type of warning to suppress .
@SafeVarargs Used to mark a method as a type- safe variadic method . The compiler will give a warning when using variadic methods, but @SafeVarargsthis warning can be suppressed by using annotations.
@FunctionalInterface Used to mark an interface to indicate that the interface is a functional interface. A functional interface is an interface that contains only one abstract method and is often used in Lambda expressions and functional programming .
@SuppressWarnings("serial") Used to suppress unserialized warnings . In a custom serializable class, if serialVersionUIDa field is not specified, the compiler will give a warning. @SuppressWarnings("serial")This warning can be suppressed by using annotations.

2.2 JDK meta-annotations

        JDK meta-annotations refer to a set of annotations provided in the Java Development Kit (JDK) for marking and defining other annotations. They are predefined annotations provided by the Java language to provide more control and additional information when writing and using custom annotations.

JDK cloud annotations
annotation Annotation description
@Retention Used to specify the retention policy of annotations. There are three retention policies to choose from, namely RetentionPolicy.SOURCE, RetentionPolicy.CLASS and RetentionPolicy.RUNTIME. Default is RetentionPolicy.CLASS . (Define retention policy for annotations)
@Documented Used to specify whether the element modified by this annotation needs to be included in the Java document. (The specified modified Annotation can be extracted into a document by the javadoc tool.)
@Target Used to specify the target element type to which the annotation applies, which can be a class, method, field, etc. Common values ​​include ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, etc.
@Inherited Used to specify whether the class modified by this annotation can be inherited by subclasses. By default, it will not be inherited by subclasses. (Specified that the modified Annotation will have inheritance)
@Repeatable Used to specify whether the annotation can be applied repeatedly to the same element, so as to achieve the effect of annotating the element multiple times.
Note:

@Retention:

@Retention(RetentionPolicy.SOURCE) //The annotation only exists in the source code and is not included in the class bytecode file.
@Retention(RetentionPolicy.CLASS) //Default retention policy, annotations will exist in the class bytecode file, but cannot be obtained at runtime.
@Retention(RetentionPolicy.RUNTIME) //The annotation will exist in the class bytecode file and can be obtained through reflection at runtime.

@Target:

@Target: Specify the location where the modified Annotation can be placed (modified target)
@Target(ElementType.TYPE) //Interface, class
@Target(ElementType.FIELD) //Attribute
@Target(ElementType.METHOD) //Method
@Target(ElementType.PARAMETER) //Method parameter
@Target(ElementType.CONSTRUCTOR) //Constructor function
@Target(ElementType.LOCAL_VARIABLE) //Local variable
@Target(ElementType.ANNOTATION_TYPE) //Annotation
@Target(ElementType.PACKAGE) //Package
For example:
@Target({ElementType.METHOD, ElementType.TYPE}), that is, this annotation can be used on methods and classes

 2.3 Custom annotations

        Custom annotations refer to using developer-defined annotations (Annotation) in Java. Annotations are a type of metadata that provide additional information about a program and can be used to add markup, configuration, and dynamic behavior to the code.

        Through custom annotations, developers can add additional information and semantics to elements such as classes, methods, and fields according to their own needs. Custom annotations need to be implemented using the annotation metaprogramming mechanism provided by Java and using specific annotation elements and annotation processors.

        The definition method of custom annotations is similar to that of ordinary interfaces. Use keywords @interfaceto define annotations, and then define annotation elements in them.

Case:
import java.lang.annotation.*;

@Target(ElementType.TYPE) // 指定注解应用的目标类型(这里是类)
@Retention(RetentionPolicy.RUNTIME) // 指定注解保留的策略(这里是运行时)
public @interface MyAnnotation {
    String value() default ""; // 定义注解元素
}

The above code example defines a MyAnnotationcustom annotation named. This annotation can be applied to a class (ElementType.TYPE) and the annotation information is retained at runtime (RetentionPolicy.RUNTIME). The annotation defines an valueannotation element named.

2. Custom annotations (used in SpringMVC)

Case explanation

Case 1: (Getting annotation values ​​on classes and methods)

Deployment test (define three constants)

Create an annotation folder, create a TranscationModel.java class and test class under the file

TranscationModel.java

package com.yx.annotation;

public enum  TranscationModel {
    Read, Write, ReadWrite
}

Corresponding test class

package com.yx.annotation;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-09-15 16:42
 * 测试类
 *
 */
public class Test01 {


    public static void main(String[] args) {
        System.out.println(TranscationModel.Read);
        System.out.println(TranscationModel.Write);
        System.out.println(TranscationModel.ReadWrite);
    }
}

operation result

Define and write three custom label classes
Custom label 01 (MyAnnotation1.java)
package com.yx.annotation.demo01;

import java.lang.annotation.*;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-09-15 16:42
 * 注解1
 * MyAnnotation1注解可以用在类、接口、属性、方法上
 * 注解运行期也保留
 * 不可继承
 */
@Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1 {
    String name();
}
Custom label 02 (MyAnnotation2.java)
package com.yx.annotation.demo01;

import java.lang.annotation.*;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-09-15 16:42
 * 注解02
 *  MyAnnotation2注解可以用在方法上
 *  注解运行期也保留
 *  不可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
    TranscationModel model() default TranscationModel.ReadWrite;
}
Custom label 03 (MyAnnotation3.java)
package com.yx.annotation.demo01;

import java.lang.annotation.*;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-09-15 16:42
 * 注解03
 * MyAnnotation3注解可以用在方法上
 * 注解运行期也保留
 * 可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {
    TranscationModel[] models() default TranscationModel.ReadWrite;
}
Related test categories
Demo1.java
package com.yx.annotation.demo01;

/**
 * @author 小李飞刀
 * @site www.javaxl.com
 *
 * 获取类与方法上的注解值
 */
@MyAnnotation1(name = "muyi")
public class Demo1 {

    @MyAnnotation1(name = "xixi")
    private Integer age;

    @MyAnnotation2(model = TranscationModel.Read)
    public void list() {
        System.out.println("list");
    }

    @MyAnnotation3(models = {TranscationModel.Read, TranscationModel.Write})
    public void edit() {
        System.out.println("edit");
    }
}
Demo1Test
package com.yx.annotation.demo01;

import org.junit.Test;

/**
 * @author 小李飞刀
 * @site www.javaxl.com
 */
public class Demo1Test {
    @Test
    public void list() throws Exception {
//        获取类上的注解
        MyAnnotation1 annotation1 = Demo1.class.getAnnotation(MyAnnotation1.class);
        System.out.println(annotation1.name());//muyi

//        获取方法上的注解
        MyAnnotation2 myAnnotation2 = Demo1.class.getMethod("list").getAnnotation(MyAnnotation2.class);
        System.out.println(myAnnotation2.model());//Read

//        获取属性上的注解
        MyAnnotation1 myAnnotation1 = Demo1.class.getDeclaredField("age").getAnnotation(MyAnnotation1.class);
        System.out.println(myAnnotation1.name());// xixi
    }

    @Test
    public void edit() throws Exception {
        MyAnnotation3 myAnnotation3 = Demo1.class.getMethod("edit").getAnnotation(MyAnnotation3.class);
        for (TranscationModel model : myAnnotation3.models()) {
            System.out.println(model);//Read,Write
        }
    }
}
Test Results
list() method test results

 edit() method test results

Case 2: (Get the annotation attribute value on the class attribute)

What is tested is the default value of value and the assignment of default default value.

Custom label class written

package com.yx.annotation.demo02;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 */
//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
    String value() default "默认value值";

    String what() default "这里是默认的what属性对应的值";
}
Test Case
package com.yx.annotation.demo02;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * 获取类属性上的注解属性值
 */
public class Demo2 {
    @TestAnnotation(value = "这就是value对应的值_msg1", what = "这就是what对应的值_msg1")
    private static String msg1;

    @TestAnnotation("这就是value对应的值1")
    private static String msg2;

    @TestAnnotation(value = "这就是value对应的值2")
    private static String msg3;

    @TestAnnotation(what = "这就是what对应的值")
    private static String msg4;
}
Test paper code
package com.yx.annotation.demo02;

import org.junit.Test;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 */
public class Demo2Test {
    @Test
    public void test1() throws Exception {
        TestAnnotation msg1 = Demo2.class.getDeclaredField("msg1").getAnnotation(TestAnnotation.class);
        System.out.println(msg1.value());
        System.out.println(msg1.what());
    }

    @Test
    public void test2() throws Exception{
        TestAnnotation msg2 = Demo2.class.getDeclaredField("msg2").getAnnotation(TestAnnotation.class);
        System.out.println(msg2.value());
        System.out.println(msg2.what());
    }

    @Test
    public void test3() throws Exception{
        TestAnnotation msg3 = Demo2.class.getDeclaredField("msg3").getAnnotation(TestAnnotation.class);
        System.out.println(msg3.value());
        System.out.println(msg3.what());
    }

    @Test
    public void test4() throws Exception{
        TestAnnotation msg4 = Demo2.class.getDeclaredField("msg4").getAnnotation(TestAnnotation.class);
        System.out.println(msg4.value());
        System.out.println(msg4.what());
    }
}
Test Results
test()02 test results

test()03 test results

test()04 test results

Case 3; (Get the attribute value corresponding to the parameter modification annotation)

Custom label class written
package com.yx.annotation.demo03;

import java.lang.annotation.*;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * 非空注解:使用在方法的参数上,false表示此参数可以为空,true不能为空
 */
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNotNull {
    boolean value() default false;
}
 Test Case
package com.yx.annotation.demo03;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * 获取参数修饰注解对应的属性值
 */
public class Demo3 {

    public void hello1(@IsNotNull(true) String name) {
        System.out.println("hello:" + name);
    }

    public void hello2(@IsNotNull String name) {
        System.out.println("hello:" + name);
    }
}
Test paper code
package com.yx.annotation.demo03;

import org.junit.Test;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;


/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 */
public class Demo3Test {

    @Test
    public void hello1() throws Exception {
        Demo3 demo3 = new Demo3();
        for (Parameter parameter : demo3.getClass().getMethod("hello1", String.class).getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//true
            }
        }
    }

    @Test
    public void hello2() throws Exception {
        Demo3 demo3 = new Demo3();
        for (Parameter parameter : demo3.getClass().getMethod("hello2", String.class).getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//false
            }
        }
    }

    @Test
    public void hello3() throws Exception {
//        模拟浏览器传递到后台的参数 解读@requestParam
        String name = "zs";
        Demo3 demo3 = new Demo3();
        Method method = demo3.getClass().getMethod("hello1", String.class);
        for (Parameter parameter : method.getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//true
                if (annotation.value() && !"".equals(name)){
                    method.invoke(demo3,name);
                }
            }
        }
    }
}
Test Results
hello1() method test results

hello2() method test results 

hello3() method test results 

hello1() method test result (name attribute is empty) 

If the name attribute value is not given, the method will not be called.

3. Aop custom annotation case (key points)

Test Case

MyLog.java

package com.yx.annotation.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    String desc();
}

Section type

MyLogAspect.java

package com.yx.aspect;

import com.yx.annotation.aop.MyLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 */
@Component
@Aspect
public class MyLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);

    /**
     * 只要用到了com.javaxl.p2.annotation.springAop.MyLog这个注解的,就是目标类
     */
    @Pointcut("@annotation(com.yx.annotation.aop.MyLog)")
    private void MyValid() {
    }

    @Before("MyValid()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        logger.debug("[" + signature.getName() + " : start.....]");
        System.out.println("[" + signature.getName() + " : start.....]");

        MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);
        logger.debug("【目标对象方法被调用时候产生的日志,记录到日志表中】:"+myLog.desc());
        System.out.println("【目标对象方法被调用时候产生的日志,记录到日志表中】:" + myLog.desc());
    }
}

Controller class

LogController.java

package com.yx.web;

import com.yx.annotation.aop.MyLog;
import org.springframework.stereotype.Controller;

/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 */
@Controller
public class LogController {

    @MyLog(desc = "这是结合spring aop知识,讲解自定义注解应用的一个案例")
    public void testLogAspect(){
        System.out.println("这里随便来点啥");
    }
}

Test Results

Situation one:

This ends the blog sharing in this issue. I hope Lao Tie will pay attention and support.

Guess you like

Origin blog.csdn.net/weixin_74352229/article/details/132888740