首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
AOP引入:OOP存在哪些局限性?
AOP常见使用场景
AOP概念:Aspect、Join Point和Advice等术语应该如何理解?
Java AOP设计模式:代理、判断和拦截器模式
Java AOP代理模式(Proxy):Java静态代理和动态代理的区别是什么?
Java AOP判断模式(Predicate):如何筛选Join Point?
Java AOP拦截器模式(Interceptor):拦截执行分别代表什么?
Spring AOP 功能概述:核心特性、编程模型和使用限制
Spring AOP编程模型:注解驱动、XML配置驱动和底层API
Spring AOP设计目标:Spring AOP与 AOP框架之间的关系是竞争还是互补?
Spring AOP Advice类型:Spring AOP丰富了哪些AOP Advice呢?
Spring AOP代理实现:为什么Spring Framework选择三种不同AOP实现?
JDK动态代理:为什么Proxy.newProxyInstance会生成新的字节码?
CGLIB动态代理:为什么Java动态代理无法满足AOP的需要?
AspectJ代理代理:为什么Spring推荐AspectJ注解?
AspectJ基础:Aspect、Join Points、Pointcuts和Advice语法和特性
AspectJ注解驱动:注解能完全替代AspectJ语言吗?
Spring核心基础:《小马哥讲Spring核心编程思想》还记得多少?
@AspectJ注解驱动
编程方式创建 @AspectJ代理
XML配置驱动 - 创建AOP代理
标准代理工厂API - ProxyFactory
@AspectJ Pointcut指令与表达式:为什么Spring只能有限支持?
XML配置Pointcut
API实现Pointcut
@AspectJ拦截动作:@Around与@Pointcut有区别吗?
XML配置Around Advice
API实现Around Advice
@AspectJ前置动作:@Before与@Around谁优先级执行?
XML配置Before Advice
API实现Before Advice
@AspectJ后置动作 - 三种After Advice之间的关系?
XML配置三种After Advice
API实现三种After Advice
自动动态代理
替换TargetSource
Spring AOP API整体设计
接入点接口 - Joinpoint
Joinpoint条件接口 - Pointcut
Pointcut操作 - ComposablePointcut
Pointcut便利实现
Pointcut AspectJ实现 - AspectJExpressionPointcut
Joinpoint执行动作接口 - Advice
Joinpoint Before Advice标准实现
Joinpoint Before Advice AspectJ实现
Joinpoint After Advice标准实现
Joinpoint After Advice AspectJ实现
Advice容器接口 - Advisor
Pointcut与Advice连接器 - PointcutAdvisor
Introduction与Advice连接器 - IntroductionAdvisor
Advisor的Interceptor适配器 - AdvisorAdapter
AdvisorAdapter实现
AOP代理接口 - AopProxy
AopProxy工厂接口与实现
JDK AopProxy实现 - JdkDynamicAopProxy
当前位置:
首页>>
技术小册>>
Spring AOP 编程思想(上)
小册名称:Spring AOP 编程思想(上)
### @AspectJ前置动作:@Before与@Around谁优先级执行? 在Spring AOP(面向切面编程)的广阔领域中,`@Before`和`@Around`是两个极其重要且常用的注解,它们分别用于定义前置通知(Before Advice)和环绕通知(Around Advice)。理解这两个注解的执行顺序及其背后的机制,对于编写高效、可维护的切面至关重要。本章将深入探讨`@Before`与`@Around`通知的优先级问题,解析它们在不同场景下的行为表现,并通过实例演示来加深理解。 #### 一、引言 Spring AOP通过代理机制实现了对目标对象的非侵入式增强,即在不修改原有代码的基础上增加新的行为。这种能力主要依赖于切面的定义,而切面中的通知(Advice)则是实现增强的关键。在Spring AOP中,`@Before`和`@Around`作为两种不同类型的通知,各自扮演着独特的角色。 - **@Before**:在目标方法执行之前执行,主要用于执行一些前置条件检查、资源准备等工作。它不能阻止目标方法的执行,也无法修改目标方法的返回值或抛出的异常。 - **@Around**:能够在目标方法执行前后执行代码,并且可以决定是否继续执行目标方法、修改其返回值或处理其抛出的异常。`@Around`通知提供了最灵活的通知类型,但相应地,其实现也较为复杂。 #### 二、@Before与@Around的优先级探讨 在Spring AOP中,当同一个切面内同时定义了`@Before`和`@Around`通知,并且它们都对同一个连接点(JoinPoint)感兴趣时,了解它们的执行顺序就变得尤为重要。实际上,`@Around`通知在`@Before`通知之前获得控制权,但请注意,这并不意味着`@Around`中的代码会先于`@Before`中的代码执行。 ##### 2.1 执行流程解析 1. **切点匹配**:首先,Spring AOP会根据切点表达式(Pointcut Expression)来确定哪些方法(连接点)需要被增强。如果`@Before`和`@Around`通知的切点表达式都匹配了同一个方法,则这两个通知都会被激活。 2. **@Around通知介入**:当方法被调用时,`@Around`通知首先介入。它会在目标方法执行前后编织代码,形成一个包裹着目标方法调用的“环绕”。 3. **@Before通知执行**:虽然`@Around`通知首先获得控制权,但它会在自己的逻辑中显式地调用`ProceedingJoinPoint.proceed()`来执行目标方法。在调用`proceed()`之前,`@Around`通知有机会执行一些前置逻辑,这看起来像是`@Before`通知的执行时机。然而,重要的是要理解,这些前置逻辑仍然是`@Around`通知的一部分,而不是`@Before`通知。 4. **目标方法执行**:`ProceedingJoinPoint.proceed()`的调用会触发目标方法的执行。 5. **@Around通知的后置逻辑**:目标方法执行完毕后,控制流回到`@Around`通知中,此时`@Around`可以执行一些后置逻辑,如处理返回值、异常等。 6. **@Before通知不参与后续处理**:值得注意的是,`@Before`通知仅在目标方法执行前执行其定义的代码,对于目标方法执行后的逻辑(如返回值处理、异常处理等),它并不参与。 ##### 2.2 示例演示 为了更好地说明这一点,我们通过一个简单的示例来演示`@Before`和`@Around`通知的执行流程。 ```java @Aspect @Component public class MyAspect { @Before("execution(* com.example.service.*.*(..))") public void beforeAdvice(JoinPoint joinPoint) { System.out.println("Before advice executed for: " + joinPoint.getSignature().getName()); } @Around("execution(* com.example.service.*.*(..))") public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("Around advice before proceeding: " + proceedingJoinPoint.getSignature().getName()); Object result = proceedingJoinPoint.proceed(); // This is where the target method is actually executed System.out.println("Around advice after proceeding: " + proceedingJoinPoint.getSignature().getName()); return result; } } @Service public class MyService { public void myMethod() { System.out.println("Executing myMethod"); } } ``` 在上述示例中,当`MyService`的`myMethod`方法被调用时,输出顺序将是: ``` Around advice before proceeding: myMethod Before advice executed for: myMethod Executing myMethod Around advice after proceeding: myMethod ``` 这个输出清晰地展示了`@Around`通知在`@Before`通知之前获得控制权,并在目标方法执行前后执行了额外的逻辑。 #### 三、深入理解 虽然`@Around`通知在`@Before`通知之前获得控制权,但我们必须清楚地认识到,`@Around`通知中的前置逻辑和`@Before`通知的逻辑在逻辑上是有区别的。`@Around`的前置逻辑是环绕通知的一部分,它可以决定是否继续执行目标方法;而`@Before`通知则仅用于在目标方法执行前执行一些前置操作,无法控制目标方法的执行。 此外,`@Around`通知的灵活性也意味着更高的复杂性。在编写`@Around`通知时,需要特别小心以确保不会无意中引入错误,比如忘记调用`proceed()`方法,这将导致目标方法不会被执行。 #### 四、结论 通过本章的探讨,我们深入理解了Spring AOP中`@Before`和`@Around`通知的执行顺序及其背后的机制。虽然`@Around`通知在逻辑上先于`@Before`通知获得控制权,但`@Before`通知的代码实际上是在`@Around`通知的某个特定阶段(即调用`proceed()`之前)执行的。这种执行顺序的理解对于编写高效、可维护的Spring AOP切面至关重要。在实际开发中,应根据具体需求选择合适的通知类型,并注意控制通知的复杂性和潜在风险。
上一篇:
API实现Around Advice
下一篇:
XML配置Before Advice
该分类下的相关小册推荐:
Java语言基础9-常用API和常见算法
Java语言基础5-面向对象初级
JAVA 函数式编程入门与实践
java源码学习笔记
Java语言基础8-Java多线程
SpringBoot合辑-高级篇
Mybatis合辑2-Mybatis映射文件
Java语言基础15-单元测试和日志技术
Java语言基础3-流程控制
Java并发编程
深入理解Java虚拟机
Java语言基础12-网络编程