springboot 整合 AOP切面编程

什么是AOP切面编程

所谓AOP就是一种编程范例,我们一般做一个项目,会分为很多个模块,这些模块中有很多不同的功能,功能中有很多不同的切入点,举个例子,现在我们有一个保存用户业务逻辑功能,我们需要在保存用户之前输入一句话,这句话必须在保存用户之前做到,一般对我们springboot项目中,针对这样的情况,我们就会在Service层的代码中加入一行,如下图所示:

===================保存用户业务逻辑=================
用户业务
UserService

  void save(User user)

  void delete(Integer id);

  User queryById(Integer id);

  ....


UserServiceImpl implement UserService

  void save(User user){
   
  	sout("=============");//业务功能-1
  	...
  	userDao.save(user);
  }

 

但是你想过没有,假设我们又要在删除用户的逻辑中也输出这样的一行内容呢?
我们是不是又要在业务逻辑层中又增加这样的一行呢?

  void delete(Integer id){
   
	sout("=============");//业务功能-1
	......
  	userDao.delete(id);
  }

那如果我们的其他模块的功能结构也需要这样这样的功能,那岂不是我们都要去加入这一行,这岂不是很麻烦吗?所以我们引入了AOP,我们能把这个要加入的功能,作为一个关注点切入进去,就不用交织在每个模块的代码中,而是作为一个单独的模块存在。
从这里我们就可以发现AOP解决了两个问题:一个是代码混乱,核心的业务逻辑代码还必须兼顾其他功能,这就导致不同功能的代码交织到一起,可读性很差。
第二,是代码分散问题。同一个功能代码分散在多个模块中,不易维护。

AOP中重要概念

切面

切面(Aspect)由切点(Pointcut)和通知(Advice)组成,它既包含了横切逻辑的定义,也包括了连接点的定义。

连接点

应用执行过程中能够插入切面的一个点,这个点可以是方法调用时,抛出异常时,甚至修改字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。
总的来说,就是程序执行的某一刻的,在这个点可以做的额外操作。

通知

切面的工作被称之为通知。

切入点

切入点是用来描述连接点的,它决定了当前代码与连接点匹配

我们可以简单的把 AOP 理解为贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。

springboot的切面编程的步骤

引入切面编程依赖

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

开发附加操作(在springboot项目新建config配置)

/**
 * 自定义切面配置类
 */
@Configuration //代表这个类是spring的配置类
@Aspect //代表这个类是切面配置类
public class MyAspectConfig {
   
    //切面Aspect=Advice附加操作+Pointcut切入点

    @Before("execution(* com.demo.springbootaoptest.service.*.*(..))")//代表这是一个核心业务逻辑执行之前的附加操作,value属性表明切书店
    public void before(JoinPoint joinPoint){
   
        System.out.println("=========前置附加操作=========");
        System.out.println("当前执行目标类: "+ joinPoint.getTarget());
        System.out.println("当前执行目标类中方法: "+ joinPoint.getSignature().getName());
    }
    @After("execution(* com.demo.springbootaoptest.service.*.*(..))")
    public void after(){
   
        System.out.println("后置通知");
    }
    @Around("execution(* com.demo.springbootaoptest.service.*.*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
   
    System.out.println("==========进入环绕的前置操作===========");
    System.out.println("当前执行类: "+proceedingJoinPoint.getTarget());
    System.out.println("方法名: "+proceedingJoinPoint.getSignature().getName());
    //放心目标方法执行
    Object proceed = proceedingJoinPoint.proceed();//继续处理  业务逻辑方法执行
    System.out.println("==========进入环绕的后置操作===========");
    return null;
}  
}

我对这上面的注解一一进行解释

  • @Aspect 用来类上,代表这个类是一个切面
  • @Before 用在方法上代表这个方法是一个前置通知方法
  • @After 用在方法上代表这个方法是一个后置通知方法
  • @Around 用在方法上代表这个方法是一个环绕的方法

另外这个方法是 上述 的 execution() 方法,用于匹配需要被 AOP 切入的方法。

execution() 方法的参数有以下几个:

"*" 表示匹配任意类型的方法。
com.demo.springbootaoptest.service 表示匹配 com.demo.springbootaoptest.service 包下的所有类。
.* 表示匹配所有类的所有方法。
(..) 表示匹配方法的任意参数。

service类

public class UserService {
   
   public void save(String name){
   
//       System.out.println("===========================");//=》额外操作
        System.out.println("处理save核心业务逻辑,调用mapper");
    }
    public void delete(Integer id) {
   
        System.out.println("===========================");

        System.out.println("处理delete核心业务逻辑,调用mapper");

    }
    public void update(String name){
   
        System.out.println("处理update核心业务逻辑,调用mapper");


    }
    public String find(String name){
   
        System.out.println("处理find核心业务逻辑,调用mapper");
        return name;
    }
}

前置结果
在这里插入图片描述

后置结果
在这里插入图片描述

环绕结果
这里要特别解释一下环绕通知的流程

在方法执行前,打印一条日志,表示进入环绕的前置操作。
获取目标方法的执行类和方法名。
调用 proceed() 方法,让目标方法执行。
在方法执行后,打印一条日志,表示进入环绕的后置操作。
在这里插入图片描述

相关推荐

  1. springboot实现Aop(通知)切面编程的案例

    2024-02-02 07:46:03       52 阅读
  2. Spring AOP 切面编程

    2024-02-02 07:46:03       36 阅读
  3. Spring aop切面编程

    2024-02-02 07:46:03       32 阅读
  4. AOP面向切面编程

    2024-02-02 07:46:03       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-02 07:46:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-02 07:46:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-02 07:46:03       82 阅读
  4. Python语言-面向对象

    2024-02-02 07:46:03       91 阅读

热门阅读

  1. uniapp【组件封装】时间戳格式化为星期

    2024-02-02 07:46:03       57 阅读
  2. 算法价值2-空间复杂度

    2024-02-02 07:46:03       54 阅读
  3. HTTP/HTTPS

    2024-02-02 07:46:03       49 阅读
  4. 使用F函数和Q函数进行高级数据库查询

    2024-02-02 07:46:03       56 阅读
  5. STM32-GPIO输入——按键检测

    2024-02-02 07:46:03       50 阅读
  6. 分享一个Qt使用的模块间通信类

    2024-02-02 07:46:03       58 阅读
  7. RPM与YUM

    RPM与YUM

    2024-02-02 07:46:03      52 阅读
  8. reactnative 调用原生UI组件(二),引入xml文件。

    2024-02-02 07:46:03       57 阅读
  9. React16源码: React中event事件监听绑定的源码实现

    2024-02-02 07:46:03       55 阅读
  10. ASP.NET Core WebAPI_解决跨域问题(前端后端)

    2024-02-02 07:46:03       53 阅读
  11. AI 代码生成

    2024-02-02 07:46:03       64 阅读
  12. springboot接入influxdb

    2024-02-02 07:46:03       58 阅读