spring aop实际开发中怎么用,Spring Boot整合AOP,spring boot加spring mvc一起使用aop,项目中使用aop

发布时间:2023年12月22日

前言:本文不介绍 AOP 的基本概念、动态代理方式实现 AOP,以及 Spring 框架去实现 AOP。本文重点介绍 Spring Boot 项目中如何使用 AOP,也就是实际项目开发中如何使用 AOP 去实现相关功能。

如果有需要了解 AOP 的概念、动态代理实现 AOP 的,请查看我的另外一篇文章:

一篇文章带你深入了解 AOP


正文开始:


Spring Boot中实际应用AOP

1、之前介绍的实现 AOP 的方式中是有 XML 文件设置。但在 Spring Boot 中,没有 XML 文件,那怎么设置 AOP?

2、实际应用中:MVC三层架构,现需要在控制器中统一进行日志的输出(有各种各样的控制器),那怎么实现?(也就是说实际应用中如何实现?)

1、Cal 接口、CalIml 接口实现类 还是跟 Spring框架实现AOP 中一样。之前的两个依赖不要,添加这个依赖:

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

2、控制器中需要打印日志,比如:调控制器中的哪个方法(接口)、方法有哪些参数、返回值。当然,你肯定可以在每个方法中写,但显然这不现实。这里用 AOP 方法将打印日志抽离出来,然后需要的时候嵌入到每个方法中

//以下代码仅是为了测试,代码不规范,请注意。

@RestController
@RequestMapping("/aop")
public class AopSpringBootTestHandler {

    @GetMapping("/findAll")
    public List<Account> findAll() {
        return Arrays.asList(new Account(1, "张三", 25), new Account(2, "李四", 26));
    }

    @GetMapping("/findById/{id}")
    public Account findById(@PathVariable Integer id) {
        return new Account(1, "张三", 25);
    }

    @GetMapping("/add")
    public boolean add() {
        return true;
    }

    @GetMapping("/update")
    public boolean update() {
        return true;
    }

    @GetMapping("/delete/{id}")
    public boolean delete(@PathVariable Integer id) {
        return true;
    }
}

自定义注解

3、自定义注解(比如:创建一个 annotation 的包,然后创建一个 LogAnnotation(可自定义,比如这里是打印日志的注解))

为什么要这个自定义注解?----> 首先你要让 AOP 知道你调了哪些方、哪些方法需要让 AOP 进行处理,所以就要让 AOP 知道这些方法,怎么知道? ----> 通过自定义注解

其次并不是所有的方法都需要进行 AOP 处理,所以通过 注解 标记。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
    //使用注解时,给注解中添加值
    String value() default "";
}

说明:@Target、@Retention、@Documented 都是元注解(描述注解的注解)

@Target 表示该注解的使用目标,其中 @Target(ElementType.METHOD) 表示只能使用在方法上:

@Retention(RetentionPolicy.RUNTIME) 表示在运行时使用该注解。

@interface 标志这是一个注解。

String value() default ""; 固定写法,表示在使用注解的时候,可以添加值,默认为空:

**使用自定义注解:**需要进行 AOP 处理的方法,标记即可

4、标记完后,同理,需要切面类,执行非业务代码(比如这里是输出日志):

@Component
@Aspect
public class CreateAspectUtil {
    /*
    我们利用自定义注解标记了哪些方法需要进行AOP处理,那真正需要处理的时候,怎么找到这些标记?
        通过 Pointcut(切入点)找到这些标记
    所以这个方法就是为了找到标记,必须是空方法体
    */
    @Pointcut("@annotation(com.example.test.aopspringboottest.annotation.LogAnnotation)")
    public void logPointCut() {

    }

    /*
    找到标记后,怎么执行日志?
    1、跟之前一样,有@Before前置通知、@After后置通知等等
      @Around注解就是将各种通知统一到一起,然后将找标记的方法放进去
    2、连接点 ProceedingJoinPoint 是 joinPoint 的子接口,
       只是ProceedingJoinPoint中有这个proceed()方法,为了获取方法的返回值
    */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        String methodArgs = Arrays.toString(joinPoint.getArgs());
        System.out.println(methodName + "方法的参数是:" + methodArgs);
        return joinPoint.proceed(); //返回目标方法(也就是业务代码)中的返回值
    }
}

演示: 启动启动类后,直接访问:

没加标记的就不会打印日志。

注意:现在还要求输出自定义注解中的值, 怎么办?----> 通过反射获取注解即可

既然获取注解,注解是添加在方法上的,所以先通过反射获取方法,怎么获取?----> 只有一个连接点,所以还是通过连接点:

@Around("logPointcut()")
public Object around(ProceedingJointPoint jointPoint) throws Throwable {
    //通过连接点获取到方法的签名
    MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
    //通过方法签名获取到方法
    Method method = methodSignature.getMethod();
    //拿到方法后,拿注解:把自定义注解的运行时类给它
    LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
    if (annotation != null) {
        //拿注解中的值,通过里面的value方法
        String value = annotation.value();
        //这个value就是注解里面的内容
        System.out.println(value);
    }
}

文章来源:https://blog.csdn.net/zhangfuping123456789/article/details/135159299
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。