Spring AOP ‌失效的原因

1. Spring AOP ‌不能拦截 protected 方法‌

核心原因

‌Spring AOP 基于代理实现‌:无论是 JDK 动态代理还是 CGLIB 代理,都只对 ‌public 方法‌ 进行增强。
‌JDK 动态代理‌:基于接口,只能代理 public 方法(接口方法默认为 public)。
‌CGLIB 代理‌:通过继承目标类生成子类,虽然理论上可以覆盖 protected 方法,但 ‌Spring AOP 明确排除了对 non-public 方法的拦截‌,以保持行为一致性。

具体表现

在 protected 方法上使用 @Transactional 等注解时,‌事务不会生效‌,且 ‌不会抛出异常‌,只是被静默忽略 ‌
Spring 在创建代理时,会通过 AbstractFallbackTransactionAttributeSource.computeTransactionAttribute() 方法判断方法可见性,若非 public,则返回 null,导致无事务增强 ‌

  • 即使 CGLIB 生成了代理类,protected 方法进入拦截链时,‌拦截器链为空‌,因此无法应用切面逻辑 ‌

2. 内部方法调用(自调用)

@Service
public class MyService {
    public void methodA() {
        methodB(); // 这里不会触发AOP
    }

    public void methodB() {
        // 事务逻辑
    }
}

解决方案:

使用 AopContext.currentProxy() 获取当前代理对象并调用。

原因:

Spring 容器会为 MyService 创建一个代理对象(假设为 MyServiceProxy)。
当外部调用 methodA() 时,实际调用的是 MyServiceProxy.methodA(),此时代理对象可以正常拦截并执行切面逻辑。
但在 methodA() 内部,methodB() 的调用是通过 this.methodB() 实现的,这里的 this 指向的是‌原始目标对象‌(即 MyService 实例),而非 MyServiceProxy。
由于调用未经过代理对象,因此 @Transactional 等基于 AOP 的注解不会生效

posted @ 2026-03-12 20:24  dvdhellohaha  阅读(30)  评论(0)    收藏  举报