2017-03-16 165 views
2

我读过Spring AOP不能拦截私有和受保护的方法,但它是以一种奇怪的方式拦截它们为什么是这样?为什么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*在那里时截获。

任何人都可以解释为什么会发生这种情况吗?

+2

除非您使用AspectJ而不是Spring AOP,否则您所描述的内容难以置信。我只是觉得你犯了一个错误。 Spring AOP永远不会拦截受保护的方法。如果您仍然认为它确实存在,请在GitHub上使用[SSCCE](http://sscce.org/)进行证明。然后,我愿意看看。 – kriegaex

+0

你可以举一个例子SSCCE。我是新来的,所以不知道如何创建一个。 –

+1

你是认真的吗?你甚至可以关注链接并阅读SSCCE的含义吗?如果你仍然不明白它的含义以及如何用你自己的代码创建一个代码,那么你要么完全缺乏作为软件开发人员的天赋,而应该尝试找到一份新工作或者你只是懒惰。我选择给你怀疑的好处,并拒绝认为你是一个糟糕的开发者。因此我认为懒惰是你的问题。所以,请尽可能尊重您的想法,您是否打算开启您的大脑并尝试帮助其他人帮助您回答您的问题? – kriegaex

回答

6

因为OP(Prateek古普塔)似乎无法(而不愿意)创造一个再现问题的小问题,而我在茶歇期间只是无聊,我很快就用Spring Boot自己创建了一个,并且非常惊讶Spring AOP确实与文档相冲突至少在某些情况下当涉及CGLIB代理时,立场与受保护方法匹配。

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


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


更新2:更新的文档的文本将在明年春季发布。如果您今天想要阅读固定文本,请参阅SPR-1611

+0

感谢您的回答。并澄清我并不懒惰,只是我对这个行业不熟悉,现在甚至没有毕业。我之前没有使用GitHub,也没有使用过StackOverflow。这是我第一次在一个行业工作(实习一个月)。我确实阅读了关于SSCCE的手册,并了解它是什么,但由于我不知道GitHub,所以我无法创建一个,这就是为什么我要求一个样本,以便至少了解它是如何完成的。 –

+3

亲爱的Prateek,对于这个行业或者StackOverflow来说,一个新的障碍是如何创建一个能够再现您的问题的小型的,降低到最小的独立示例?我看不到那个。对不起,如果你的代码中有可重现的问题,你应该能够从你的大项目中提取一个最小版本的小项目。你不需要毕业就可以做到这一点。能够将你的代码检入Git仓库是一项基本的开发技巧,如果没有它,任何一个开发人员如何生存?你可以在一天中学习。 – kriegaex

+0

我刚刚更新了我的答案,并附有新票状态和解释。 – kriegaex

1

任何人都可以解释为什么会发生这种情况吗?

由于Spring的AOP框架的基于代理的性质,保护的方法是通过定义不拦截,既不是JDK代理(其中,这是不适用),也不是CGLIB代理(其中这在技术上是可行的,但不建议用于AOP目的)。

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

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

当执行该代码双方的getName和getNamesprotected被截获

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

这里前面的通配符匹配任何修饰的方法(公有,保护和私有)和任何返回类型。参数列表中的两个点匹配任意数量的参数。

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

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

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

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

虽然你所说的都是正确的,但它并不回答OP的原始问题。 – kriegaex

+0

“@Pointcut(”execution(protected * *。*(..))))和'@Before(“execution(* com.tutorialspoint.Student + .getNamesprotected(..))”)'都不能拦截在我的问题中,受保护的方法只有'* Name *'是拦截受保护的,因为我使用的是Spring AOP,所以理想情况下不应该发生这种情况。 –

相关问题