【问题标题】:Spring-AOP pointcut not working?Spring-AOP 切入点不起作用?
【发布时间】:2017-03-22 11:35:26
【问题描述】:

下面是我的代码sn-p:

ServiceImpl.java

@Service
public class ServiceImpl implements Service {
  private Response worker(Audit send) throws ArgumentException {
    System.out.println("STEP_1");
    worker(send.getRequest(), send.getId());
  }

  private Response worker(Request request, String id) throws ArgumentException {
    System.out.println("STEP_2");
    try {
      //throwing some exception
    } catch (Exception e) {
      System.out.println("STEP_3");
    }
  }
}

现在,我想要的是每当NullPointerException 被从方法worker(Request request, String id) 抛出时,如上所示,我想要执行一些特定的任务。为此,我编写了一个 Aspect 类,如下所示:

MyAspect.java

@Aspect
@Component
public class MyAspect{
  @Pointcut("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
  private void someOperation(Request request) {}

  @Before("someOperation(request)")
  public void process(Request request) {
    System.out.println("SUCCESS");
  }

  @AfterThrowing("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
  public void doRecoveryActions() {
    System.out.println("EXCEPTION_SUCCESS");
  }
}

电流输出:

STEP_1 
STEP_2
STEP_3

所需的输出:

STEP_1 
STEP_2
STEP_3
SUCCESS
EXCEPTION_SUCCESS

如您所见,MyAspect.java 没有被触发,因此不会打印值。 这可能是什么原因?

注意:

  1. 我也尝试将 worker 设为公共课程,但没有成功。

  2. 还尝试更改方法的名称以消除任何同样不起作用的重载问题。

  3. 到目前为止,尝试了各种其他切入点表达式都是徒劳的。

  4. 在我的应用程序中,还有其他方面类工作得非常好。

【问题讨论】:

  • 您是否确保已将 MyAspect 添加到您的应用程序上下文中?
  • 我认为我没有为此输入任何条目。另外我不知道应用程序上下文到底是什么/在哪里。我正在使用现有系统。
  • 我会首先确保 sprint 知道 MyAspect(即它已被添加到应用程序上下文中)。这通常通过application-context.xml 或通过类路径扫描来完成。你已经在类上有@Component,这很好,但你只需要确保 spring 知道这个类。
  • 在您费心缩小方面的范围之前,首先应该运行它。我认为阅读精美的 Spring 手册是有意义的,尤其是关于 Spring AOP 的章节,如果之后您还有问题,请回到这里。作为一个新手在现有的应用程序上工作不是不学习那里使用的技术的借口,因为你弄乱了代码。我无意冒犯,但 StackOverflow 并不是您将工作委派给他人的合适平台。
  • 如果您想在这里得到好的答案,给您的另一个建议:请创建一个Minimal, Complete, and Verifiable example,以便其他用户能够重现和理解您的问题。

标签: java spring-aop


【解决方案1】:

您犯了一个典型的 Spring AOP 初学者错误:您假设它适用于私有方法,但正如文档中明确指出的那样,它不是。 Spring AOP 基于动态代理,仅在通过 JDK 代理实现接口时适用于公共方法,并且在使用 CGLIB 代理时还适用于受保护和包范围的方法。

如果你想从某个方面拦截worker()方法,你应该公开它。

P.S.:成熟的 AspectJ 也适用于私有方法,但在这里切换到另一个 AOP 框架将是矫枉过正。


更新:您的代码中还有其他问题:

  • 第一个worker 方法,即使您将其公开,也不会返回任何内容。最后一条语句应该是return worker(send.getRequest(), send.getId());,而不仅仅是worker(send.getRequest(), send.getId());
  • 你的切入点com.xyz.myapp.ServiceImpl.worker() 永远不会匹配,因为它有一个空参数列表,但你的方法有参数。 args() 在这里对您没有帮助。
  • 你的切入点的语法也是错误的,因为它没有指定方法的返回类型,甚至没有*。此外,方法名本身是不够的,它应该包含在一个实际的切入点类型中,例如execution()。 IE。你想写这样的东西:
@Pointcut("execution(* com.xyz.myapp.ServiceImpl.worker(..)) && args(request, ..)")
private void someOperation(Request request) {}

【讨论】:

  • 我也尝试将它们公开,但这对我也不起作用。
  • AOP 是否在同一个项目的其他情况下工作?我们需要找出是否存在配置问题或只是您方面的问题。
  • 是的,它在同一个项目中工作。我还检查了其他类,发现它们是独立类,即它们没有扩展/实现任何其他类/接口。但在我的例子中,该类实现了一个接口“Service.java”。另一件事是方法 worker() 仅特定于我的类,它不是被覆盖的方法。
【解决方案2】:

要拦截抛出异常的方法,您可以使用以下代码(仅在方法公开时有效):

 @AfterThrowing(pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",throwing="ex")
         public void doRecoveryActions(NullPointerException ex) {
          // ...
         }

来源:Spring AOP

【讨论】:

    猜你喜欢
    • 2018-06-13
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多