【问题标题】:How does this point cut work in Spring AOP?这个切入点在 Spring AOP 中是如何工作的?
【发布时间】:2019-11-01 07:39:37
【问题描述】:

我正在学习 Spring AOP,并从 spring-framework-reference 的 AOP 部分中的一个示例中得到以下切入点表达式:Proceeding with Arguments

@Around("execution(List<Account> find*(..)) && " +
        "com.xyz.myapp.SystemArchitecture.inDataAccessLayer() && " +
        "args(accountHolderNamePattern)")
public Object preProcessQueryPattern(ProceedingJoinPoint pjp,
        String accountHolderNamePattern) throws Throwable {
    String newPattern = preProcess(accountHolderNamePattern);
    return pjp.proceed(new Object[] {newPattern});
}

据我了解,这个切入点表达式是不正确的,因为 and 条件永远不会满足。我是否遗漏了一些非常明显的东西?

我还尝试了以下操作 (ref):

@Component
public class TestBean {
    public void testMethod() {
    }
}

方面类

@Before("com.test.bean.TestBean.testMethod()")
    public void testAspect() {
        System.out.println("Worked");
    }

失败了

Caused by: java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut testMethod
    at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:319)

【问题讨论】:

    标签: spring-aop


    【解决方案1】:

    两个切入点都有语法错误。如果你想拦截一​​个方法,你不能只写一个没有execution() 的方法签名。另外请不要忘记指定返回类型或至少为任何返回类型指定*

    第一个切入点在语法上是正确的,如下所示:

    @Around(
      "execution(List<Account> find*(..)) && " +
      "execution(* com.xyz.myapp.SystemArchitecture.inDataAccessLayer()) && " +
      "args(accountHolderNamePattern)"
    )
    

    但是它仍然不会匹配任何方法,因为&amp;&amp;(逻辑与)要求两个方法执行同时为真,这是不可能的。 find*(..)inDataAccessLayer() 正在执行,绝不会同时执行。您可以改用||(逻辑或),但是args() 匹配器将是模棱两可的,因此切入点将再次无效。除非您向我解释您想要实现的目标,否则我无法告诉您如何修复您的切入点。现在的样子没有任何意义。

    至于第二个切入点,你可以这样修复:

    @Before("execution(* com.test.bean.TestBean.testMethod())")
    

    您引用的错误消息意味着 AspectJ 解析器认为您指的是命名切入点,而不是您预期的方法执行。

    【讨论】:

    • 谢谢@kriegaex。第一个切入点直接从 spring-framework-reference 文档中的示例复制。我很困惑,因为我没想到文档本身中的切入点表达式不正确。现在很清楚了。我理解正确。第二个例子是理解错误文档的第二部分,你已经解释得很好。
    • 不不,没有错误是Spring手册,只是您的示例代码不完整。我刚刚检查过:在 Spring 手册中,如果您搜索 inDataAccessLayer(),您将找到一个命名的切入点定义,正如我在解释第二个问题时提到的:@Pointcut("within(com.xyz.someapp.dao..)") public void inDataAccessLayer() {}。如果将其添加到示例方面,则语法有效。你不能只是复制一个例子的一部分,你需要把它放到上下文中。
    • 我的错!现在明白了。 and 条件仍然是不正确的,对吧?。
    • 不,不会。实际上是execution(List&lt;Account&gt; find*(..)) &amp;&amp; within(com.xyz.someapp.dao..*),这很好。 Spring手册中唯一的问题是他们在切入点中写了..而不是..*,可能是一个错字。
    猜你喜欢
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多