【SpringBoot】Spring AOP详解

目录

一、什么是Spring AOP

二、SpringAOP实现

2.1 添加Spring AOP依赖 

2.2 定义切面和切点

2.3 解释AspectJ

2.4 什么是通知 


一、什么是Spring AOP

AOPAspect Oriented Programming)即面向切面编程,是对某一类事件的集中处理。面向切面编程(AOP)是一种编程范式,旨在将横切关注点(如日志记录、事务管理、权限验证等)从业务逻辑代码中分离出来,从而提高代码的可重用性、可维护性和模块性。Spring AOP 通过代理模式在运行时动态地将横切关注点织入到目标对象中。

AOP 的组成:切面(Aspect)、切点(Pointcut)、通知(Advice)。AOP 的主要核心概念有:

切面(Aspect)

  • 定义:切面是一个模块,它封装了横切关注点,包含了定义切点和通知的代码。
  • 作用:将横切关注点模块化,便于复用和管理

连接点(Join Point)

  • 定义:程序执行过程中能够插入切面的点,如方法调用、异常抛出等。
  • 在Spring AOP中:连接点通常是方法的调用。

切点(Pointcut)

  • 定义:切点定义了一组连接点,用于确定通知应该在哪些连接点上执行。
  • 表示方式:通常使用表达式来匹配连接点,如AspectJ表达式。

通知(Advice)

  • 定义:通知是切面在某个连接点执行的动作,它包含了在连接点执行的代码。

类型

  • 前置通知(Before):在目标方法执行前执行。
  • 后置通知(After):在目标方法执行后执行。
  • 返回通知(After Returning):在目标方法成功执行后执行。
  • 异常通知(After Throwing):在目标方法抛出异常后执行。
  • 环绕通知(Around):在目标方法执行前后执行,并可以控制目标方法的执行。

二、Spring AOP实现

Spring AOP 实现的主要步骤有:

  1. 添加 SpringAOP 的依赖
  2. 定义切面
  3. 定义切点
  4. 实现通知

2.1 添加Spring AOP依赖 

pom.xml 文件中加入以下 Spring AOP 依赖: 

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

2.2 定义切面和切点

Spring AOP 中,@Pointcut  注解用于定义一个切点,它描述了哪些方法会被 AOP 切面(Aspect)拦截。切点表达式通常使用 AspectJ 的切点表达式语言来指定。@Pointcut 注解本身不执行任何操作,但它可以与其他 AOP 注解(如@Before@After@Around等通知)结合使用,以定义在哪些连接点(Join Points)上应用横切逻辑。

//定义切面
@Aspect
@Component
public class UserAspect {
    //定义切点
    @Pointcut("execution(* com.example.demo.controller.UserController.* (..))")
    public void pointcut(){};
}

定义切面使用 @Aspect 注解,定义切点使用 @Ponintcut 注解。

在上述代码中,@Aspect 标记了 UserAspect 为一个切面类,它包含了一个或多个横切关注点(Advice),@Component 将该切面类注册到 Spring 中为一个 Bean,使它能够被 Spring 容器管理。@Pointcut 定义了 pointcut() 方法为一个切点,切点表达式采用了  execution() 表达式即 AspectJ 表达式。

采用 AspectJ 表达式主要是为了与 Spring AOP 结合,以实现对 MyBatis 操作的拦截和增强。AspectJ 表达式定义了哪些连接点(如方法调用)会被切面(Aspect)拦截。


2.3 解释AspectJ

AspectJ ⽀持三种通配符:
  • * :匹配任意字符,只匹配⼀个元素(包,类,或⽅法,⽅法参数)。
  • .. :匹配任意字符,可以匹配多个元素 ,在表示类时,必须和 * 联合使⽤。
  • + :表示按照类型匹配指定类的所有类,必须跟在类名后⾯,如 com.cad.Car+ ,表示继承该类的 所有⼦类包括本身。
切点表达式由切点函数组成,其中 execution() 是最常⽤的切点函数,⽤来匹配⽅法,
语法为: execution(<修饰符><返回类型><包.类.⽅法(参数)><异常>)其中修饰符和异常可以省略,其余不可省略。因此上述的切点为匹配到 UserController 类中的所有任意方法。
//匹配UserController类中的所有方法
execution(* com.example.demo.controller.UserController.* (..))

2.4 什么是通知 

Spring AOP 中,通知(Advice)是切面的具体实现,用于在连接点(通常是方法的执行点)上执行特定的逻辑。通知可以分为以下几类,每类通知的作用如下:

  1. 前置通知(Before Advice)

  • 作用:在目标方法执行之前执行。可以用于执行权限检查、准备资源等操作。
  • 示例:在执行业务方法之前,检查用户是否具有执行该方法的权限。
  1. 后置通知(After Advice)

  • 作用:在目标方法执行之后执行,无论目标方法是否抛出异常。可以用于清理资源、记录日志等操作。
  • 示例:在业务方法执行后,记录方法执行的时间和结果。
  1. 返回通知(After Returning Advice)

  • 作用:在目标方法正常返回后执行。可以用于处理返回值、记录日志等操作。
  • 示例:在业务方法成功返回后,对返回值进行格式化处理。
  1. 异常通知(After Throwing Advice)

  • 作用:在目标方法抛出异常后执行。可以用于处理异常、记录错误日志等操作。
  • 示例:在业务方法抛出异常时,捕获异常并记录到错误日志中。
  1. 环绕通知(Around Advice)

  • 作用:在目标方法执行前后执行。可以在方法执行前进行前置处理,在方法执行后进行后置处理,甚至可以控制目标方法是否执行。
  • 示例:在业务方法执行前开启事务,在方法执行后提交或回滚事务。

创建 UserAspect 公共类:

//定义切面
@Aspect
@Component
public class UserAspect {
    //定义切点
    @Pointcut("execution(* com.example.demo.controller.UserController.* (..))")
    public void pointcut(){
        System.out.println("hello this is pointcut");
    };

    //定义前置通知
    @Before("pointcut()")
    public void before(){
        System.out.println("执行了前置通知");
    };

    //定义后置通知
    @After("pointcut()")
    public void after() {
        System.out.println("执行了后置通知");
    }

    //环绕通知
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前通知");
        Object ret =  joinPoint.proceed();
        System.out.println("环绕后通知");
        return ret;
    }

    //返回之前通知
    @AfterReturning("pointcut()")
    public void afterReturning() {
        System.out.println("执行return之前的通知");
    }
}

创建 UserController 类:

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/getuser")
    public String getUser() {
        System.out.println("hello user");
        return "hello user";
    }
}

浏览器输入 localhost:8080/user/getuser 后,浏览器输出:

 控制台输出:


本篇博客到这里就结束了,感谢各位的观看。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只爱打拳的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值