Spring自定义注解实现AOP做简单的拦截/权限校验

关于AOP的资料:AOP(Spring的面向切面编程)
(1)新增依赖,pom.xml文件中新增:
<!--ASPECT-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
(2) 实现自定义注解:

在这里插入图片描述

是一个interface
package com.jojo.cloud.aspect;

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JojoTalk {
    
    
    // 这里定义的属性,是在使用注解时候可以选的,如果不传,就用default后面的属性
    int id() default 100;
    String name() default "测试注解";
    boolean edit() default false;
}

Documented:负责标记和修饰该注解,可以被JavaDoc接口工具文档化
Retention:负责管理该注解的生命周期,通过RetentionPolicy.XXXXX指定。(SOURCE:源码保留,编译后消失。 CLASS:编译时存在,运行时丢失。 RUNTIME:编译,运行,源码都保留,可以被反射发现并调用)
Target:负责该注解的作用范围。也就是该注解可以加在哪里,通过ElementType.XXXX 可以指明。
TYPE:类,接口,枚举上。
METHOD: 方法上。
PARAMETER: 参数上。
LOCAL_VARIABLE:局部变量上。
CONSTRUCTOR:构造方法上。

(3)新增切面方法

@Aspect
@Component
public class JojoTalkMethod {
    
    
	
	// 表明以JojoTalk方法作为切入点,同时以talkSome作为增强的代理方法,接下来的几种通知类型全部针对talkSome进行,也等于间接对JojoTalk进行增强
    @Pointcut("@annotation(com.jojo.cloud.aspect.JojoTalk)")
    public void talkSome(){
    
    }

    @Around("talkSome()")
    public Object Interceptor(ProceedingJoinPoint joinPoint){
    
    
        System.out.println("AOP环绕通知开始~~~");
        Object retmsg=null;
        try {
    
    
            // 通过proceed()调用目标方法,同时触发Before前置通知,如果在环绕通知中不通过切入点JoinPoint.proceed()调用目标方法,前置通知会失效。
            joinPoint.proceed();
        } catch (Throwable e) {
    
    
            e.printStackTrace();
        }
        System.out.println("环绕通知结束");
        Object result = null;
        return result;
    }

    @Before("talkSome()")
    public void before(JoinPoint joinPoint) throws Throwable {
    
    
        MethodSignature sign =  (MethodSignature)joinPoint.getSignature();
        Method method = sign.getMethod();
        JojoTalk jojoTalk = method.getAnnotation(JojoTalk.class);
        System.out.println("前置通知:注解里的属性(在AOP增强型方法中可以对其进行逻辑处理)"
                + jojoTalk.id()+jojoTalk.name()+jojoTalk.edit());
    }

    @After("talkSome()")
    public void after() {
    
    
        System.out.println("后置通知:执行结束,撒花!");
    }

}
(4)Controller方法中调用:
@GetMapping("/testAOP")
    @JojoTalk()
    public void testAOP(){
    
    
        System.out.println("执行了目标方法!!!!!");
    }
这样就使用上了刚刚定义好的@JojoTalk自定义注解,同时也可以使用自定义属性,不传的话就是默认,通过这一步可以做一些业务判断逻辑处理:

在这里插入图片描述

(5)测试:

在这里插入图片描述
这里可以看得很清楚,环绕通知执行,前置通知执行,目标方法执行,环绕通知收尾,后置通知收尾。

(6)通过传进来的参数做不同的业务逻辑处理/权限校验/判断

只需要在@Before前置通知方法里面加上:
在这里插入图片描述

(7)如果这个接口标注在多个Controller里面,发生报错或者记录日志时候,怎么样快速知道是哪个Controller?

两种方法:
(1)定义一个Source参数在自定义注解中,每次使用自定义注解都必须传入该参数。(非常不合理,非常麻烦,而且万一写错了,排查问题都找半天)
(2)通过@Around环绕通知方法中的JoinPoint连接点获取调用者信息:
在这里插入图片描述
在这里插入图片描述

完结,撒花~~~

猜你喜欢

转载自blog.csdn.net/whiteBearClimb/article/details/108995893
今日推荐