SpringBoot自定义注解配合AOP

自定义注解

package com.example.servlet;

import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Author: CQ
 * @Date: 2020/11/19 10:46
 */
// 此注解的使用位置
@Target(ElementType.METHOD)
//该@Chec的生命周期
@Retention(RetentionPolicy.RUNTIME) 
public @interface MySysLog {
    
    String decipher();

    int length();
    
    /**
     * String: 数据类型,
     * paramValues(): 参数名称,大括号是格式标准;
     **/
    String[] paramValues();

    /**
     * default: 默认的提示信息
     **/
    String message() default "参数不为指定值";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

注解解释
@Target
  • 该注解用于@Check注解上,可以表明Check注解的使用位置,下面是Target中的ElementType的释义

  • 当@Target中的参数为那个字段时,表明这个注解只能使用在什么位置
    	ElementType.TYPE:说明该注解只能被声明在一个类前。
    	ElementType.FIELD:说明该注解只能被声明在一个类的字段前。
    	ElementType.METHOD:说明该注解只能被声明在一个类的方法前。
    	ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。
    	ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。
    	ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。
    	ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。
    	ElementType.PACKAGE:说明该注解只能声明在一个包名前 
    
@Retention
  • 该注解用于@Check注解上,可以表明Check注解的生命周期,下面是Retention中RetentionPolicy的释义

  • 当@Retention中的参数为那个字段时,表明这个注解的可用范围
    RetentionPolicy.SOURCE: 注解只保留在源文件中
    RetentionPolicy.CLASS : 注解保留在class文件中,在加载到JVM虚拟机时丢弃
    RetentionPolicy.RUNTIME: 注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解。
    

AOP切面

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.example.demo.annotation.MySysLog;

import lombok.extern.slf4j.Slf4j;

/**
 * @author CQO
 * @since 2023/03/12 13:52
 */
@Slf4j
@Aspect
@Component
public class SystemLogAspect {


    /**
     * <P>拦截使用@MySysLog注解的方法</P>
     * @param point
     * @param mySysLog 自定义注解
     * @return
     * @throws Throwable
     */
    @Around("@annotation(mySysLog)")
    public Object around(ProceedingJoinPoint point, MySysLog mySysLog) throws Throwable {

        MethodSignature signature = (MethodSignature)point.getSignature();
        MySysLog annotation = signature.getMethod().getAnnotation(MySysLog.class);
        String decipher = annotation.decipher();
        int length = annotation.length();
        System.out.println("获取注解上传入的参数: "+decipher +"  "+length);
        /**
         * 在这里有一个问题,那就是如何动态的获取注解上的参数,
         * 有一个思路就是可以看看Spring中@Valve是怎么获取配置文件的参数
         */

        String name = point.getTarget().getClass().getName();
        System.out.println("被切面的类相对路径:  "+name);

        String name1 = signature.getName();
        System.out.println("被切面的类名:  "+name1);

        Object[] args = point.getArgs();
        System.out.println("切面传入的参数:"+args);

        return point.proceed();

    }

}

测试注解和AOP

Controller
import com.example.demo.annotation.MySysLog;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author CQO
 * @since 2023/03/12 13:53
 */
@RequestMapping("logAspect")
@RestController
public class MySystemLogAspectController {

    @MySysLog(decipher = "ChenQ",length = 28)
    @PostMapping("test")
    public void MySystemLogAspectControllerTest(@RequestBody UserAspectTest userAspectTest){

        System.out.println(userAspectTest);
    }


}
实体类
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

/**
 * @author CQO
 * @since 2023/03/12 14:18
 */
@Getter
@Setter
@EqualsAndHashCode
public class UserAspectTest {

    private String name;

    private String age;
}
输出结果

tips

  • 如果注解只能用于字段上的获取方式
package com.example.demo.annotation;

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

/**
 * @author CQO
 * @since 2023/03/07 16:42
 */

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

    String decipher();

    int length();
}

package com.example.demo.annotation;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;

/**
 * @author CQO
 * @since 2023/03/07 16:45
 */
public class MyFiledTest {

    @MyFiled(decipher = "用户名", length = 12)
    private String userName;

    @MyFiled(decipher = "用户名", length = 12)
    private String user;

    @Test
    public void test() {

        Class<MyFiledTest> myFiledTestClass = MyFiledTest.class;
        Field[] declaredFields = myFiledTestClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            // 判断这个字段是否有MyFile注解
            if (declaredField.isAnnotationPresent(MyFiled.class)) {
                MyFiled annotation = declaredField.getAnnotation(MyFiled.class);
                System.out.println("字段: " + declaredField.getName() + "   姓名: " + annotation.decipher() + "   长度: "
                    + annotation.length());
                // 字段: userName   姓名: 用户名   长度: 12
				// 字段: user   姓名: 用户名   长度: 12
            }
        }
    }
}

posted @ 2023-03-12 15:32  unknown-n2  阅读(47)  评论(0编辑  收藏  举报