【问题标题】:How can I make an incorrect pointcut expression throw an exception?如何使不正确的切入点表达式引发异常?
【发布时间】:2019-08-02 09:50:33
【问题描述】:

我有以下切入点表达式:

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

现在如果建议的方法重命名为applyTo,那么切入点不再正确,建议将永远不会触发。建议的失败不会被注意到,因为不正确的切入点不会在应用程序启动或运行时引发任何异常。

我查看了 Spring AOP 文档,但找不到使切入点因异常而失败的方法。有什么办法吗?

【问题讨论】:

  • 为什么会失败? (我的意思是我知道为什么在这种情况下 - 但总的来说)它是一个有效的切入点,恰好没有匹配的代码。谨慎重构
  • 我不认为你可以。基本上,您只需重命名一个方法。你的所有代码都知道:你不想在那里再次触发 aop。也许您可以使用注释来标记切入点而不是方法名称。

标签: java spring aop


【解决方案1】:

Antonio 100% 正确,这里没有错误。切入点只是说:“如果您碰巧找到与此描述匹配的连接点,请在此处应用我的方面建议”。

  • Joinpoint 匹配是在 Spring AOP 的运行时完成的。所以它本质上是动态的。
  • 对于带有加载时编织 (LTW) 的 AspectJ 也是如此。类加载器总是有机会加载新类,然后动态匹配切入点和编织到其中的方面代码。所以你永远不会知道你已经“完成”了方面编织。您何时会发出警告或错误?
  • 如果您将 AspectJ 与编译时编织 (CTW) 一起使用,如果在编译期间通知的切入点根本无法匹配任何连接点,AspectJ 编译器将发出警告 Xlint:adviceDidNotMatch。但是想一想,它永远不仅仅是一个信息或一个警告,因为如果你编译一个方面模块,你以后想将其应用于多个应用程序或一个应用程序中的其他模块,无论你使用的是 CTW 还是 LTW ,匹配的连接点仅在稍后编织这些模块时才能找到。

所以这没有错误,否则你永远不能使用方面库或 LTW。方面的整个想法是它们独立于应用程序代码。

此外,如果您将 99% 的 apply 方法重命名为 applyTo 但出于某种原因 - 意图或疏忽 - 保留单个 apply 方法,切入点仍然匹配,因此您的假设错误不会是产生了。您的错误不是语法而是语义,方面编织者怎么知道?正如安东尼奥所说,谨慎重构。在这种特殊情况下,您可以将切入点更改为apply*,然后它将匹配applyapplyTo,但也匹配applyMagic,这可能是您不想要的。

Stultuske 匹配注解而不是方法名的想法就是我所说的“穷人的 AOP 方法”,因为它仍然将 AOP 相关信息分散在整个代码库中,因此不能兑现 AOP 的承诺,即不仅摆脱代码纠缠和分散。分散现在仅适用于注释而不是内联方法代码。如果您在应用程序代码中根本看不到 AOP,我个人最喜欢它,除非您希望以声明方式应用某些功能并且出于某种原因在源代码中使用注释(例如 @Transactional)记录它。但这是一个品味问题,我可能仍会尝试将声明放入切面切入点而不是应用程序。只有当整体匹配模式太复杂而无法在切入点中处理时,我才可能使用注释。链接注释和方面的广泛实践,甚至使某种“AOP 设计模式”被误导并因此被过度使用,IMO。该模式有其很好的用途,但比我看到的要少得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 2020-10-29
    相关资源
    最近更新 更多