AOP是Spring中, 个人认为较为抽象的一个思想. 一般来说, 学习一个新东西, 第一件事是先看看这个知识点的定义是什么. 同时要注意, 同一事物的定义可以有很多, 毕竟定义没有绝对的对与错, 只有准确与否.
而初次接触AOP的定义, 第一感觉可能就是抽象, 或者说看不懂, 这里面也有翻译的锅. 简而言之, AOP, 是对某一类事物进行统一的集中的处理, 大致包含四个方面: 切面(Aspect), 切点(Pointcut), 连接点(Join Point)以及通知(Advice).
切面: 可以简单的理解为一个类, 类里包含了若干个切点与通知.
切点: 用于定义判定规则, 即以此作为条件决定是否要进行统一处理.
连接点: 简单理解成所有要进行判定的方法.
通知: 具体的要处理的措施
可能这样还是有点抽象, 画图举例说明一下:
假设, 有一个过滤器. 需要在一堆大小不一的豆子当中过滤出小的豆子用于碾磨成粉. 这个过程其实就可以抽象成AOP. 切面就是这个过滤装置, 连接点就是要进行过滤的豆子, 它们有大有小, 而切点就是那个漏斗, 只有小的能够过去, 碾磨成粉就是通知, 即具体的要对过滤出来的方法具体实现的措施.
所以AOP就是以切点作为某种规则, 对所有方法过滤, 过滤出需要处理的方法, 再以通知进行处理.
具体到代码中, 若要实现一个AOP, 首先, 得创建一个Maven项目引入AOP依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.7.9</version></dependency>
其次, 创建一个切面, 切面中就得包含切点与通知. 而切面的确定靠的是注解@Aspect, 告诉框架这是一个切面, 然后就是在这个类中写出具体的切点以及通知. 二者的确定靠的也是注解. 切点所使用的是@Pointcut, 而通知则分为多个通知, 分别为前置(@Before), 后置(@After), 返回(@AfterReturning), 异常(@AfterThrowing), 环绕(@Around). 这些不同的通知所对应的是不同时机, 即前置通知就是在目标方法执行前执行通知, 返回通知就是在目标方法返回数据后执行通知.
package com.example.demo.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect //告诉框架这是一个切面类
@Component //随着框架的启动而启动
public class UserAspect {/*** 切点(配置拦截规则)*/@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut(){}/*** 定义前缀通知*/@Before("pointcut()")public void beforeAdvice(){System.out.println("执行了前缀通知!");}/*** 定义后缀通知*/@After("pointcut()")public void afterAdvice(){System.out.println("执行了后缀通知!");}/*** 环绕通知*/@Around("pointcut()")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("进入环绕通知");Object obj = null;//执行目标方法obj = joinPoint.proceed();System.out.println("退出环绕通知");return obj;}
}
注意, 环绕通知的写法与其他通知略微不同. 这是规定, 不存在为什么. 而切点当中注解后面的括号就是过滤规则, 即要对哪个文件哪个包哪个类底下的哪个方法进行拦截过滤. 后面还跟了一个空方法, 这个空方法的作用就是通知时用于跟在注解后面, 以告诉框架以哪个规则进行拦截, 因为一个切面可以包含多个切点, 就以空方法名进行区分.
----------------------------------------最后编辑于2023.9.16 下午四点左右