AOP失效(调用内部方法情况)

首先切面定义正确:
在这里插入图片描述
然后使用注解标记切点:ss方法提供给外部调用,SS方法调用S方法,S方法被标记为切点。
在这里插入图片描述
执行结果:
在这里插入图片描述
切面未生效! why?
原因:当类中的一个方法调用同一个类中的另一个方法时,Spring AOP 不会生效,因为内部调用不会经过代理对象
解决办法:调用内部方法时走代理对象调用就好(这是个笨办法,期待大佬给出更好的解决办法)
在这里插入图片描述

在 Spring AOP 中,自调用(即类内部方法调用另一个带有 AOP 增强的方法)时,AOP 通常不会生效。这是因为 Spring AOP 是基于代理机制实现的,当一个类的方法AOP 增强时,Spring 会创建该类的代理对象,并通过代理对象来执行增强逻辑。然而,在类内部直接使用 `this` 调用其他方法时,调用并不会经过代理对象,从而导致 AOP 增强失效。 ### 解决方案 #### 1. 使用 `AopContext.currentProxy()` 获取当前代理对象 可以通过 `AopContext.currentProxy()` 方法获取当前类的代理对象,然后通过代理对象显式地调用目标方法。这种方式可以确保调用链经过代理,从而触发 AOP 的增强逻辑。 ```java @Override public void methodB() { System.out.println("method B"); ((YourService) AopContext.currentProxy()).methodA(); } ``` 需要注意的是,使用此方式时必须启用 expose-proxy 配置,即在 Spring 配置中设置 `<aop:aspectj-autoproxy expose-proxy="true"/>`,否则无法正确获取到代理对象[^4]。 #### 2. 启用 CGLIB 代理以支持类级别的 AOP 默认情况下,Spring AOP 使用 JDK 动态代理来创建代理对象,但这仅适用于实现了接口的类。如果希望对没有实现接口的类也应用 AOP,则需要启用 CGLIB 代理。可以通过配置 `proxy-target-class="true"` 来启用 CGLIB 代理: ```xml <aop:aspectj-autoproxy proxy-target-class="true" /> ``` 这样即使类未实现接口,Spring 也会使用 CGLIB 创建代理对象,从而确保 AOP 在类内部调用中仍然有效[^2]。 #### 3. 将需要增强的方法抽取到独立的服务类中 为了避免自调用问题,可以将需要 AOP 增强的方法提取到一个新的服务类中,并通过依赖注入的方式调用它。这样可以确保调用是通过 Spring 管理的代理对象进行的,从而保证 AOP 生效。 例如,将 `sayHi` 方法从 `HelloService` 提取到一个新的 `TransactionService` 中,并通过注入该服务实例来调用方法: ```java @Component public class HelloService { @Autowired private TransactionService transactionService; public void anotherSayHi(String msg) { transactionService.sayHi(msg); } } ``` 这种方式不仅解决了自调用问题,还能提高代码的模块化和可测试性[^3]。 #### 4. 显式注入自身并调用方法 另一种解决方案是通过依赖注入的方式将当前类的代理对象注入到自身中,然后通过注入的代理对象调用目标方法。例如: ```java @Component public class YourService { @Autowired private YourService selfProxy; public void methodB() { System.out.println("method B"); selfProxy.methodA(); } @Transactional public void methodA() { // 业务逻辑 } } ``` 由于 `selfProxy` 是由 Spring 注入的代理对象,因此通过它调用方法将经过 AOP 拦截,从而保证增强逻辑生效[^1]。 #### 5. 使用 AspectJ 完全编译时织入 如果上述基于代理的解决方案仍无法满足需求,可以考虑使用 **AspectJ** 进行完全编译时织入(Compile-time Weaving)。与 Spring AOP 不同,AspectJ 可以直接修改字节码,无需依赖代理机制,因此即使是类内部的自调用也可以正常应用切面逻辑。这需要引入 AspectJ 相关依赖并配置编译插件,适合对性能要求较高或需要更全面 AOP 支持的场景。 --- ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Brldy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值