SpringMVC custom annotations and usage

I. Introduction

1 Introduction:

In Spring MVC, we can use custom annotations to extend and customize our applications. Custom annotations are special annotations defined through Java's annotation mechanism. They can be applied to controller classes, methods or method parameters to achieve different functions and behaviors. (Annotation related classes are included in the java.lang.annotation package.)

 2. Achievable functions

1. Route mapping : You can define a custom annotation to annotate the controller method to specify the URL mapping path of the method.

2. Permission control : You can define a custom annotation to mark methods that require permission verification to implement simple permission control logic.

3. Parameter verification : You can define a custom annotation to mark method parameters, and then combine AOP and other technologies to verify and verify parameters before or after method execution.

4. Logging : You can define a custom annotation to mark the methods that require logging, so as to achieve unified processing of logs.

5. Cache control : You can define a custom annotation to mark methods that require cache management, thereby realizing automated cache management.

 3. Use custom annotation process

1. Define annotations: Use annotation syntax to define custom annotations on the relevant annotation classes. You can specify the target scope and attributes of the annotations.

2. Use of tags: Use custom annotations on controller classes, methods or method parameters to identify where custom logic needs to be applied.

3. Process annotations: Through Spring's AOP, interceptor and other mechanisms, classes, methods or parameters marked with specific custom annotations are processed to implement related functions.

2. Java decomposition class

1. JDK basic annotations

@Override: override

Application: generally appears in interface implementation classes

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@SuppressWarnings(value = "unchecked") 

Application: Suppress editor warnings

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

2. JDK meta-annotations

@Retention: Define the retention policy of annotations
@Retention(RetentionPolicy.SOURCE) //Annotations only exist in the source code and are not included in class bytecode files
@Retention(RetentionPolicy.CLASS) //Default retention policy, annotations will be in It exists 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: 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
Note: Multiple locations can be specified, for example:
@Target({ElementType.METHOD, ElementType.TYPE}), that is, this annotation can be used on methods and classes

@Inherited: Specifies that the modified Annotation will have inheritance

@Documented: Specifies that the modified Annotation can be extracted into a document by the javadoc tool.

 3. Custom annotations

Annotation classification (Annotation can be divided into two categories according to whether it contains member variables):

Mark Annotation:
Annotation without member variables; this kind of Annotation only uses its own existence to provide information

Metadata Annotation:
Annotation containing member variables; they can accept (and provide) more metadata;

4. How to customize annotations?

Using the @interface keyword, the definition process is very similar to defining an interface. It should be noted that the
   member variables of Annotation are declared in the form of a parameterless method in the Annotation definition. The method name and return value type define the member variable. The name and type,
   and we can also use the default keyword to set a default value for this member variable;

 3. Use custom annotations

1.Configure pom.XMl

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xzs</groupId>
    <artifactId>spboottest01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spboottest01</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
<!--            <scope>test</scope>-->
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. Understand what an enumeration is?

   An enumeration class is a special data type in Java that is used to define a fixed set of named constants. Enumeration types provide a more powerful, safer, and more readable way to represent a group of related constants. In Java, enumeration types are defined through the keyword enum.

Role: The role of the enumeration class is to provide a type-safe way to represent a fixed set of values ​​and avoid errors that may occur when using numeric or string constants. By using enumeration types, you can restrict variables to only take predefined values, and you can use the names of these constants in your code to improve readability and maintainability.

package com.xzs.annotation;

public enum  TranscationModel {
    Read, Write, ReadWrite
}

 3. Custom annotation class

1.MyAnnotation1 
package com.xzs.annotation.pi;

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1 {
    int id();

    String name();
}

2、MyAnnotation2

package com.xzs.annotation.pi;

import com.xzs.annotation.TranscationModel;

import java.lang.annotation.*;
 
/**
 *  MyAnnotation2注解可以用在方法上
 *  注解运行期也保留
 *  不可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
    TranscationModel model() default TranscationModel.ReadWrite;

}

 .3、MyAnnotation3

package com.xzs.annotation.pi;

import com.xzs.annotation.TranscationModel;

import java.lang.annotation.*;
 
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {
    TranscationModel[] models() default TranscationModel.ReadWrite;


}

.4、TestAnnotation

package com.xzs.annotation.pi;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
    String value() default "默认value值";

    String what() default "这里是默认的what属性对应的值";

}

Case 1:

1. Create a test class

package com.xzs.annotation.pi;

import com.xzs.annotation.TranscationModel;

@MyAnnotation1(id = 1, name = "lei")
public class DemoTest {

    @MyAnnotation1(id = 2, name = "sx")
    private Integer age;

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

    @MyAnnotation3(models = {TranscationModel.Read, TranscationModel.Write, TranscationModel.ReadWrite})
    public void up() {
        System.out.println("up");
    }

}

 2. Get the annotations on the class

    @Test
    public void list() throws Exception {
//        获取类上的注解
        MyAnnotation1 annotation1 = DemoTest.class.getAnnotation(MyAnnotation1.class);
        System.out.println(annotation1.name() + "/" + annotation1.id());
}

 3. Get the annotations on the method

 @Test
    public void list2() throws Exception {
//        获取方法上的注解
        MyAnnotation2 myAnnotation2 = DemoTest.class.getMethod("select").getAnnotation(MyAnnotation2.class);
        System.out.println(myAnnotation2.model());

    }

 

4. Get annotations on attributes

 @Test
    public void list3() throws Exception {
//        获取属性上的注解
        MyAnnotation1 myAnnotation1 = DemoTest.class.getDeclaredField("age").getAnnotation(MyAnnotation1.class);
        System.out.println(myAnnotation1.name() + "/" + myAnnotation1.id());
    }

 .5. Annotations on the traversal method

  @Test
    public void edit() throws Exception {
        MyAnnotation3 myAnnotation3 = DemoTest.class.getMethod("up").getAnnotation(MyAnnotation3.class);
        for (TranscationModel model : myAnnotation3.models()
        ) {
            System.out.println(model);
        }
    }

Case 2:

 1. Test category:

package com.xzs.annotation.p2;

import com.xzs.annotation.pi.TestAnnotation;

public class Demo2 {
    @TestAnnotation(value = "这就是value对应的值_msg1", what = "这就是what对应的值_msg1")
    private static String msg1;

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

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

    @TestAnnotation(what = "这就是what对应的值:msg4")
    private static String msg4;

}

package com.xzs.annotation.p2;

import com.xzs.annotation.pi.TestAnnotation;
import org.junit.jupiter.api.Test;


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());
    }
}

 

 

 

 Case 3:

Custom annotations

package com.xzs.annotation.p3;

import java.lang.annotation.*;
 
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNotNull {
    boolean value() default false;

}

Test class

package com.xzs.annotation.p3;

import org.junit.jupiter.api.Test;

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

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("hello1:" + annotation.value());//true
                System.out.println(("-----------hello1----------"));
            }
        }
    }
 
    @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("hello2:" + annotation.value());//false
                System.out.println(("-----------hello2----------"));
            }
        }
    }
 
    @Test
    public void hello3() throws Exception {
//        模拟浏览器传递到后台的参数 解读@requestParam
        String name = "tqg";
        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);
                }
                System.out.println(("-----------hello3----------"));  }
        }
    }}

 

4. Aop custom annotation application

1. Custom annotations

package com.xzs.annotation.aop;

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

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    String desc();
}

 2. Configure spring-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!--spring框架与mybatis整合配置文夹加载到spring上下文中-->
    <import resource="spring-mybatis.xml"></import>
   <context:annotation-config/>
    <!-- 用注解方式注入bean,并指定查找范围:com.javaxl.ssh2及子子孙孙包-->
    <context:component-scan base-package="com.xzs"/>
    <!--开启动态代理-->
    <aop:aspectj-autoproxy/>
</beans>

3. Application notes

package com.xzs.annotation.aop;


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;



@Component
@Aspect
public class MyLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);
 
   
    @Pointcut("@annotation(com.xzs.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());
    }
}

 4. Controller layer code

package com.xzs.web;

import com.xzs.annotation.aop.MyLog;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

@Component
@RequestMapping("/log")
public class LogController {

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

}

 result:

Guess you like

Origin blog.csdn.net/weixin_72997875/article/details/132914153