Spring-AOP 切入点不起作用?

Spring-AOP pointcut not working?

下面是我的代码片段:

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) 中抛出时,如上所示,我想执行一些特定的任务。为此,我写了一个方面 class,如下所示:

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 设为 public class,但没用。

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

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

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

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

如果你想从一个方面拦截它,你应该制作worker()方法public。

P.S.: 成熟的 AspectJ 也适用于私有方法,但切换到另一个 AOP 框架在这里就太过分了。


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

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

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

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

来源:Spring AOP