Spring Boot 自定义注解实现AOP

1. 自定义注解规则

  1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口.
  2. 参数成员只能用public或默认(default)这两个访问权修饰
  3. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组.
  4. 要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation对象,因为你除此之外没有别的获取注解对象的方法
  5. 注解也可以没有定义成员, 不过这样注解就没啥用了

2. 定义自定义注解时相关注解介绍

@Documented 注解 功能:指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值。

@Retention 注解 功能:指明修饰的注解的生存周期,即会保留到哪个阶段。 RetentionPolicy的取值包含以下三种:
SOURCE:源码级别保留,编译后即丢弃。 CLASS:编译级别保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值。
RUNTIME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。

@Target 注解 功能:指明了修饰的这个注解的使用范围,即被描述的注解可以用在哪里。 ElementType的取值包含以下几种:

TYPE:类,接口或者枚举 FIELD:域,包含枚举常量 METHOD:方法 PARAMETER:参数 CONSTRUCTOR:构造方法
LOCAL_VARIABLE:局部变量 ANNOTATION_TYPE:注解类型 PACKAGE:包

3. 使用Spring的AOP先加入Maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

4. 先创建一个自己定义的注解

@Documented
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    
    
}

5.AOP配置

@Aspect//切面
@Pointcut//定义需要切面的地方
@annotation//当执行的方法上拥有指定的注解时生效。
@After
@Before
@Around

@Component
@Aspect
public class MyAnnotationAspect {
    
    
    @Pointcut("@annotation(com.example.demo.annotation.MyAnnotation)")
    private void myAnnotation() {
    
    
    }

    /**
     * 环绕通知
     */
    @Around("myAnnotation()")
    public void advice(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
        System.out.println("around begin...");
        //执行到这里走原来的方法
        joinPoint.proceed();
        System.out.println("around after....");
    }

    @Before("myAnnotation()")
    public void record(JoinPoint joinPoint) {
    
    
        System.out.println("Before");
    }

    @After("myAnnotation()")
    public void after() {
    
    
        System.out.println("After");
    }
}

ProceedingJoinPoint和JoinPoint说明
AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:

1.JoinPoint
java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
Signature getSignature() :获取连接点的方法签名对象;
java.lang.Object getTarget() :获取连接点所在的目标对象;
java.lang.Object getThis() :获取代理对象本身;
2.ProceedingJoinPoint
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。

6.Controller测试

@RestController
public class MyAnnotationController {
    
    

    @MyAnnotation
    @RequestMapping("/aa")
    public void testAnnotation(){
    
    
        System.out.println("我正在测试自定义注解。。。");
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45163291/article/details/128657981