SpringBoot中基于注解使用AOP

1. 加入依赖

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

2. 创建注解类

/**
 * @author H
 * @date 2022/10/20
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AopAnnotation {

    String value();
    
    int type() default 1;

}

3. 创建切面类

/**
 * @author H
 * @date 2022/10/20
 */
@Aspect
@Component
public class AopAnnotationAspect {

    /**
     * 这里的路径填写自定义注解的全路径
     */
    @Pointcut("@annotation(com.aop.demo.aop.AopAnnotation)")
    public void testAnnotation() {
    }

    /**
     * 在方法执行之前执行
     * @param joinPoint
     */
    @Before("testAnnotation()")
    public void beforeCut(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("[Before] 注解方式aop开始拦截,当前拦截的方法名:" + method.getName());
    }

    /**
     * 在方法执行之后执行
     * @param joinPoint
     */
    @After("testAnnotation()")
    public void afterCut(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("[After] 注解方式aop执行的方法:" + method.getName() + "执行完了");
    }

    /**
     * 围绕方法的执行
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("testAnnotation()")
    public Object aroundCut(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("[Around] 开始进入环绕通知");
        // 获取注解参数
        System.out.println("=========获取注解参数开始========");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        AopAnnotation annotation = method.getAnnotation(AopAnnotation.class);
        System.out.println(annotation.value());
        System.out.println(annotation.type());
        System.out.println("=========获取注解参数完成========");

        Object proceed = joinPoint.proceed();
        System.out.println("[Around] 准备退出环绕");
        return proceed;
    }

    /**
     * 在方法返回结果之后执行
     * @param joinPoint
     * @param result
     */
    @AfterReturning(value = "testAnnotation()", returning = "result")
    public void afterReturn(JoinPoint joinPoint, Object result) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("[AfterReturning] 注解方式AOP拦截的方式执行成功,进入返回通知拦截,方法名为:" + method.getName() + ",返回结果为:" + result.toString());
    }

    /**
     * 在方法抛出异常后执行
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "testAnnotation()", throwing = "e")
    public void afterThrow(JoinPoint joinPoint, Exception e) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("[AfterThrowing] 注解方式aop进入方法异常拦截,方法名为:"+  method.getName() + ",异常信息为:" + e.getMessage());
    }

}

注意:切面类必须加@Component注解交由spring容器管理,否则切面不生效

3. 创建控制器

/**
 * @author H
 * @date 2022/10/20
 */
@RestController
public class UserController {

    @Autowired
    private UserController userController;

    @AopAnnotation  // 加到控制器上也会生效
    @GetMapping("login/{username}")
    public String login1(@PathVariable String username) {
        String test = userController.test(); // 调用加了aop注解的方法,不能用this调用
        return test;
    }

    @Deprecated
    @AopAnnotation(value = "你好,世界", type = 3)
    protected String test() {
        return "a";
    }

}

执行结果:

[Around] 开始进入环绕通知
=========获取注解参数开始========
你好,世界
3
=========获取注解参数完成========
[Before] 注解方式aop开始拦截,当前拦截的方法名:test
[AfterReturning] 注解方式AOP拦截的方式执行成功,进入返回通知拦截,方法名为:test,返回结果为:a
[After] 注解方式aop执行的方法:test执行完了
[Around] 准备退出环绕

注意:

1、@AopAnnotation注解不能加到private修饰的方法上,否则注解不生效;

2、如果A方法调用B方法,在B方法上加了@AopAnnotation注解,不能用this调用,需要注入当前对象,用对象调用,否则不走aop,注解不生效;

3、在controller的web地址映射方法上加@AopAnnotation注解,也是会生效。

4. 多个AOP注解的执行顺序

经过测试,在方法上改变两个注解的顺序不会影响执行顺序。一个方法上多个AOP注解,若要控制执行顺序,可以在切面类上加@Order(1)注解来控制,数字越小,越先执行。

    @AopAnnotation("111")
    @AopAnnotation1("222")
    @GetMapping("test")
    public String test() {
        System.out.println("------> 方法执行");
        return "success";
    }
[Around AopAnnotation] 开始进入环绕通知
[Before AopAnnotation] 注解方式aop开始拦截,当前拦截的方法名:test
[Around AopAnnotation1] 开始进入环绕通知
[Before AopAnnotation1] 注解方式aop开始拦截,当前拦截的方法名:test
------> 方法执行
[AfterReturning AopAnnotation1] 注解方式AOP拦截的方式执行成功,进入返回通知拦截,方法名为:test,返回结果为:success
[After AopAnnotation1] 注解方式aop执行的方法:test执行完了
[Around AopAnnotation1] 准备退出环绕
[AfterReturning AopAnnotation] 注解方式AOP拦截的方式执行成功,进入返回通知拦截,方法名为:test,返回结果为:success
[After AopAnnotation] 注解方式aop执行的方法:test执行完了
[Around AopAnnotation] 准备退出环绕
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值