Spring AOP相关知识详解

1.AOP介绍

1.1 面向切面编程 - Aspect Oriented Programming (AOP)

AOP,作为OOP面向对象编程的一种功能补充。AOP是Spring框架重要的组件,作为IOC的补充。

是一种思想,本质是为了解耦。将横切逻辑代码抽取出去,通过简单的配置,使用动态代理的方式添加到目标方法中,做到无侵入、便捷。

Spring 框架通过定义切面, 通过拦截切点实现了不同业务模块的解耦。面向切面编程是一种编程范式,主要用于分离那些横切多个业务模块的关注点,比如日志记录、事务管理、权限验证等这些功能就属于横切关注点。

关注点是指在软件开发过程中,系统中某个特定的业务功能、特性、需求或者设计,是开发人员重点关注、考虑、实现的部分。

横切关注点是跨越多个模块、多个层次或者多个业务功能的关注点

1.2 优点

横向解决代码重复的问题
(1)解耦横切关注点:将与业务逻辑不直接相关的功能,横切的功能解耦。如日志记录、事务管理、权限验证等从业务代码中分离出来,使得业务逻辑更加清晰,易于理解和维护。

(2)代码复用:多个业务模块可以共用同一个切面,避免了代码的重复编写。

(3)灵活、可扩展:可以方便地添加、删除或修改切面的逻辑,而不需要对业务逻辑进行大规模的改动。

2.AOP的概念

我之前的一篇博文写的

2.1 连接点、切入点、通知、切面:

(1)连接点:可以成为切入点

(2)切入点(在哪干):需要增强的目标方法。用来确定在哪些地方应用切面的逻辑,比如可以定义在某个类的所有方法上,或者某个包下的特定方法上。
//明确了哪些连接点会被通知。@Pointcut 注解定义了一个切入点,切入点表达式 execution(* com.tutorialspoint..(…)) 表示匹配 com.tutorialspoint 包下的所有类的所有方法。

   @Pointcut("execution(* com.tutorialspoint.*.*(..))")
   private void selectAll(){
   }

(3)通知(干什么):是定义在切面中的一段代码,指定了在切面的切点位置上要执行的具体动作逻辑。(什么时候做、做什么)。通知是在目标方法执行前、后执行的方法。通知用于在目标方法执行的特定时机插入额外的行为,从而实现对目标对象方法的增强或扩展。通知是在目标方法执行前、后执行的方法。比如前置通知可以在目标方法执行前做一些事情,后置通知在目标方法执行后做一些事情,环绕通知则可以在目标方法执行前后都进行相应的操作。

//在切入点所选择的连接点上执行的代码
@Before("selectAll()")
public void beforeAdvice(){
   
    System.out.println("Going to setup student profile.");
}

(4)切面=切入点+通知。切面是对横切关注点的抽象,它把切点和通知组合在一起。

@Aspect 注解将 Logging 类标记为一个切面类。这个类中包含了切入点的定义(selectAll() 方法)和各种通知的实现(beforeAdvice()、afterAdvice() 等方法),它将日志记录的逻辑封装在一起,形成了一个切面。

(5)织入:织入把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。就是通过动态代理对目标对象方法进行增强的过程。运行时织入。

“织入(Weaving)” 是一个核心概念,它描述的是将切面(Aspect)中的通知(Advice)应用到目标对象(Target Object)的具体连接点(Join Point)上,从而创建出代理对象(Proxy Object)的过程。

(6)目标对象:被一个或者多个切面所通知的对象,也被称作被通知对象。Spring AOP是通过运行时代理实现的,所以这个对象永远是一个被代理的对象。
切入点所匹配的方法,这些方法是应用程序中原本就存在的业务逻辑方法,AOP 通过在这些方法的执行过程中插入通知来增强其功能。

2.2 注解

2.2.1 通知类型

(1)@Before 前置通知(Before Advice)
定义:在目标方法执行之前执行的通知。
作用:常用于进行一些准备工作,如参数校验、权限判断、初始化操作等。例如,在一个用户登录的方法前,使用前置通知可以进行用户名和密码的非空校验,若校验不通过则直接返回错误信息,不执行后续的登录逻辑。
(2)@After 后置通知(After Advice)
定义:在目标方法执行之后执行的通知,无论目标方法是否抛出异常都会执行。
作用:可用于进行一些资源清理、日志记录等操作。比如在一个文件上传的方法执行后,使用后置通知可以关闭文件流,释放相关资源,或者记录文件上传的结果信息,无论上传是否成功都可以进行相应的记录。
(3)@AfterReturning 正常返回通知(After Returning Advice)
定义:在目标方法正常执行完成并返回结果后执行的通知。
作用:可以对目标方法的返回值进行处理或记录。例如,在一个查询数据库获取用户信息的方法后,使用返回通知可以对查询到的用户信息进行加密处理,或者记录查询结果以便进行数据分析。
(4)@After-Throwing 异常通知(After Throwing Advice)
定义:在目标方法执行过程中抛出异常时执行的通知。
作用:主要用于处理异常情况,如记录异常信息、进行异常的统一处理或回滚事务等。比如在一个数据更新的方法中,如果出现数据库连接异常或数据冲突异常,异常通知可以捕获并记录这些异常,同时可以根据异常类型进行相应的处理,如提示用户重新操作或回滚到之前的状态。
(5)@Around 环绕通知(Around Advice)
定义:环绕通知可以在目标方法执行前后都添加自定义逻辑,它将目标方法的执行包裹在其中,是最强大也最灵活的一种通知类型。环绕通知是最常用的通知类型。
作用:可以决定目标方法是否执行、何时执行以及如何执行,还可以对目标方法的参数和返回值进行修改。例如,在一个远程服务调用的方法上添加环绕通知,可以在调用前进行网络连接的检查和参数的预处理,在调用后对返回结果进行缓存处理或错误处理等 。

@Aspect
public class PerformanceAspect {
   
    @Around("execution(* com.example.service..*.*(..))")
    public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
   
        long startTime = System.currentTimeMillis();
        Object result = pjp.proceed();
        long endTime = System.currentTimeMillis();
        System.out.println("方法执行时间: " + (endTime - startTime) + " 毫秒");
        return result;
    }
}
2.2.1.1 通知的优先级排序

优先级:异常通知>后置通知>前置通知>后置返回通知。
(只要异常通知报错,无论前置通知、后置通知、后置返回通知报错,都将返回的是异常通知)

如果有多个通知想要在同一连接点运行会发生什么?
在“进入”连接点的情况下,最高优先级的通知会先执行(所以给定的两个前置通知中,优先级高的那个会先执行)。
在“退出”连接点的情况下,最高优先级的通知会最后执行。(所以给定的两个后置通知中, 优先级高的那个会第二个执行)。

2.2.2 其他重要注解

@Aspect:用来定义一个类作为切面。
@Pointcut:用于定义切点的位置。用于定义切点表达式,将切点表达式单独提取出来,以便在多个通知中重复使用,提高代码的可维护性。

@Aspect
public class LoggingAspect {
   
    @Pointcut("execution(* com.example.service..*.*(..))")
    public void serviceMethods() {
   }

    @Before("serviceMethods()"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值