springboot自定义注解实现aop

增强方法也称为通知方法,指标注有@Before、@After、@AfterReturning、@AfterThrowing、@Around注解的Java方法。其中,有前置增强、后置增强、返回增强、异常增强和环绕增强五种增强方式。

一、目录结构

二、项目依赖

 <!--aop相关依赖 开始-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!--aop相关依赖 结束-->

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>
        <!--springboot-web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

三、代码

自定义注解

package at.xx.annotation;

import java.lang.annotation.*;

/**
 * @description:触发aop的自定义注解
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
    String value() default "";
}

切面类

package at.xx.aspect;

import at.xx.annotation.MyAnnotation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MyAspect {
    @Before("@annotation(at.xx.annotation.MyAnnotation)")
    public void before(JoinPoint joinPoint) {
        //获取方法参数
        Object[] args = joinPoint.getArgs();
        //获取方法签名(能得到方法的些信息,如:方法名)
        Signature signature = joinPoint.getSignature();
        //方法名称
        String name = signature.getName();
        System.out.println(name + "前置增强,方法参数:" + args[0] + args[1]);
    }

    @After("@annotation(at.xx.annotation.MyAnnotation)")
    public void after(JoinPoint joinPoint) {
        //获取方法参数
        Object[] args = joinPoint.getArgs();
        //获取方法签名
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        System.out.println(name + "后置增强,方法参数:" + args[0] + args[1]);
    }

    @AfterReturning(value = "@annotation(at.xx.annotation.MyAnnotation)", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        System.out.println(name + "返回增强,方法结果:" + result);
    }

    /**
     *
     * @param joinPoint
     * @param e 通过该参数指定异常,触发该增强
     */
    @AfterThrowing(value = "@annotation(at.xx.annotation.MyAnnotation)", throwing = "e")
    public void AfterThrowing(JoinPoint joinPoint, NullPointerException e) {
        System.out.println("异常增强"+e);
    }

    @Around("@annotation(at.xx.annotation.MyAnnotation)")
   public Object around(ProceedingJoinPoint joinPoint){
        //方法返回值
        Object result=null;
        //获取方法参数
        Object[] args = joinPoint.getArgs();
        args[0]="张子成";
        //获取方法签名
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        //获取注解
        MyAnnotation annotation = signature.getMethod().getAnnotation(MyAnnotation.class);
        //获取注解参数值
        String value = annotation.value();
        //todo  原方法执行前增加的业务逻辑
        try {
             result = joinPoint.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        //todo 原方法执行后增加的业务逻辑
        return result;
    }
}

controller 层(原有逻辑方法)

package at.xx.controller;

import at.xx.annotation.MyAnnotation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Mr.Z
 * @Create 2023-01-29 21:03
 * @description:
 */
@RestController
public class AopController {
    @MyAnnotation
    @GetMapping("/test/before")
    public String testAop(String arr1,String arr2){
        System.out.println("方法运行");
        String s=null;
        System.out.println(arr1+arr2);
        //s.equals("x");
       // int i=1/0;
        return "aop";
    }
}

四、具体介绍

1、前置增强

前置增强(@Before,又称前置通知):在目标方法执行之前执行。

@Before("@annotation(at.xx.annotation.MyAnnotation)")
    public void before(JoinPoint joinPoint) {
        //获取方法参数
        Object[] args = joinPoint.getArgs();
        //获取方法签名
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        System.out.println(name + "前置增强,方法参数:" + args[0] + args[1]);
    }

2、后置增强

后置增强(@After,又称后置通知):在目标方法执行后执行,无论目标方法运行期间是否出现异常。

注意:后置增强无法获取目标方法执行结果,可以在返回增强中获取。

 @After("@annotation(at.xx.annotation.MyAnnotation)")
    public void after(JoinPoint joinPoint) {
        //获取方法参数
        Object[] args = joinPoint.getArgs();
        //获取方法签名
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        System.out.println(name + "后置增强,方法参数:" + args[0] + args[1]);
    }

3、返回增强

返回增强(@AfterReturning,又称返回通知):在目标方法正常结束后执行,可以获取目标方法的执行结果。

@AfterReturning(value = "@annotation(at.xx.annotation.MyAnnotation)", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        System.out.println(name + "返回增强,方法结果:" + result);
    }

4、异常增强

异常增强(@AfterThrowing,又称异常通知):目标方法抛出异常之后执行,可以访问到异常对象,且可以指定在出现哪种异常时才执行增强代码。

/**
     *
     * @param joinPoint
     * @param e 通过该参数指定异常,触发该增强
     */
    @AfterThrowing(value = "@annotation(at.xx.annotation.MyAnnotation)", throwing = "e")
    public void AfterThrowing(JoinPoint joinPoint, NullPointerException e) {
        System.out.println("异常增强"+e);
    }

5、环绕增强

环绕增强:目标方法执行前后都可以织入增强处理。

@Around("@annotation(at.xx.annotation.MyAnnotation)")
   public Object around(ProceedingJoinPoint joinPoint){
        //方法返回值
        Object result=null;
        //获取方法参数
        Object[] args = joinPoint.getArgs();
        args[0]="张子成";
        //获取方法签名
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        //获取注解
        MyAnnotation annotation = signature.getMethod().getAnnotation(MyAnnotation.class);
        //获取注解参数值
        String value = annotation.value();
        //todo  原方法执行前增加的业务逻辑
        try {

             result = joinPoint.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        //todo 原方法执行后增加的业务逻辑
        return result;
    }

五、使用场景及注意事项

使用场景:

在不改变原有代码的情况下,增加新的业务逻辑时使用aop(重点掌握@Around);

注意:

1、@Before、@After、@AfterReturning和@AfterThrowing修饰的方法可以通过声明JoinPoint 类型参数变量获取目标方法的信息(方法名、参数列表等信息);@Around修饰的方法必须声明ProceedingJoinPoint类型的参数,该变量可以决定是否执行目标方法;

2、@Before、@After、@AfterReturning和@AfterThrowing修饰的方法没有返回值;而@Around修饰的方法必须有返回值,返回值为目标方法的返回值;

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,关于SpringBoot自定义注解AOP的问题,我可以为您提供一些基本的介绍和示例代码。 首先,AOP(Aspect-Oriented Programming)是一种编程范式,它可以在不修改业务逻辑代码的情况下,对应用程序进行横切关注点的切面处理。而Spring AOP作为Spring框架的一部分,提供了一种基于代理模式的AOP实现。 在使用Spring AOP的过程中,自定义注解可以作为切点表达式的一部分,通过对注解的解析,实现对被注解的方法或类的切面处理。下面是一个简单的示例代码,演示如何通过自定义注解实现对方法的AOP处理: 首先,定义一个自定义注解: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { String value() default ""; } ``` 然后,在需要被拦截的方法上添加该注解: ```java @Service public class MyService { @MyAnnotation("myAnnotation") public void doSomething() { System.out.println("do something..."); } } ``` 接下来,使用AspectJ的@Aspect注解定义一个切面类,并在该类中定义一个切点,用于匹配被@MyAnnotation注解的方法: ```java @Aspect @Component public class MyAspect { @Pointcut("@annotation(com.example.demo.annotation.MyAnnotation)") public void myAnnotationPointcut() {} @Before("myAnnotationPointcut()") public void beforeMyAnnotation() { System.out.println("before myAnnotation..."); } } ``` 最后,启动SpringBoot应用程序,调用MyService的doSomething方法,就可以看到输出结果: ```java before myAnnotation... do something... ``` 以上就是一个简单的SpringBoot自定义注解AOP的示例。通过使用自定义注解,可以更加方便地实现对应用程序的切面处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值