为什么 Spring AOP 在某些情况下会拦截受保护的方法?

Why does Spring AOP intercept protected methods under certain circumstances?

我读到 Spring AOP 无法拦截私有和受保护的方法,但它以一种奇怪的方式拦截它们,这是为什么?

我有这些我想拦截的功能:

public String getName(String string) {
   System.out.println("Name : " + name + string);
   return name;
}

protected String getNamesprotected(String string) {
  System.out.println("Name : " + name + string);
  return name;
}

这是我的 @Aspect 代码:

@Aspect
public class Logging {

    @Before("execution(* com.tutorialspoint.Student.*Name*(..))")
    public void beforeAdvice(JoinPoint joinPoint){
       System.out.println("Going to setup student profile."+joinPoint.getSignature().toString());
    }
}

当执行此代码时,getName 和 getNamesprotected 都被拦截但是当我执行此代码时:

@Aspect
public class Logging {

    @Before("execution(* com.tutorialspoint.Student.getNamesprotected(..))")
    public void beforeAdvice1(JoinPoint joinPoint){
       System.out.println("Going to setup student profile."+joinPoint.getSignature().toString());
    }
}

然后什么都没有被拦截。我也尝试用 *getNamesprotected* 替换 getNamesprotected 但它仍然没有拦截。它仅在 *Name* 存在时拦截。

谁能解释一下为什么会这样?

Can anyone explain me why this is happening?

由于 Spring 的 AOP 框架基于代理的性质,根据定义,受保护的方法不会被拦截,无论是对于 JDK 代理(这不适用)还是对于 CGLIB代理(这在技术上是可行的,但不推荐用于 AOP 目的)。

因此,任何给定的切入点都将仅与 public 方法匹配!

如果您的拦截需要包括 protected/private 方法甚至构造函数,请考虑使用 Spring 驱动的原生 AspectJ 编织,而不是 Spring 基于代理的 AOP 框架。

When this code is executed both getName and getNamesprotected are intercepted

 @Before("execution(* com.tutorialspoint.Student.*Name*(..))")

此处前面的通配符匹配具有任何修饰符(public、protected 和 private)和任何 return 类型的方法。参数列表中的两个点匹配任意数量的参数。

试试这个它应该执行你的受保护方法

@Pointcut("execution(protected * *.*(..))")

如果它适合你,你也可以试试这个(我不是 100% 确定)

 @Before("execution(* com.tutorialspoint.Student+.getNamesprotected(..))")

因为 OP (Prateek Gupta) 似乎无法(相当不愿意)创造一点 SSCCE 重现问题,而我只是在茶歇期间感到无聊,所以我很快用 Spring 启动并且非常惊讶确实 Spring AOP,与文档相矛盾,至少在某些情况下,当涉及 CGLIB 代理时,它与受保护的方法相匹配。

因此,我为 Spring 的 Jira 问题跟踪器注册了一个帐户,并将此回归报告为 SPR-15354。如果对 Spring 开发团队的回答感兴趣,您可能想要订阅该票证的更新。


更新: 回复我的工单的人告诉我这是文档问题。正如 2006 年的 SPR-1611 告诉我们的那样,这已经在 Spring 1.2.7 中有意更改,但从未在文档中找到它的方式。底线:受保护的方法可以通过 Spring AOP 捕获,这不是偶然的,但已经 12 年没有记录了。


更新 2: 更新的文档文本将在下一个 Spring 版本中。今天要看固定文,引用在SPR-1611.