Aspectj 切入点表达式不适用于一种方法,而适用于单个 class 中的另一种方法

Aspectj Pointcut expression not working for one method and working for another method in single class

我已经在控制器中编写了以下代码。

对于此 controllerMethod 方法,aspectj Pointcut 表达式工作正常,但对于 executeService 方法,Aspect 不起作用。

@RequestMapping(value = "URL", method = RequestMethod.POST)
public ModelAndView controllerMethod(@ModelAttribute ModelAttribute reqModel, HttpServletRequest req, HttpServletResponse res) {

    try {
        response = executeService(param1, param2);

    } catch (Exception e) {

    }

    }       
private ResponseObject executeService(String param1, String param2){
    //Code....
}

我写的方面如下。

@Before("execution(* com.*.*.Controller.executeService(..))")
public void logBefore(JoinPoint joinPoint) {
    logger.info("Before aspect: " + joinPoint.getSignature().getName());
}

你能告诉我问题出在哪里吗?我需要在调用 executeService 方法之前执行方面。

需要@RequestMapping(value = "URL", method = RequestMethod.POST) 直接 executeService 然后它的工作。

因为AOP不拦截内部调用,所以可以添加一个自控字段,通过self.method(...)调用内部方法。 以下代码:

@Controller
public class ExampleController{

    @Autowired
    private ExampleController self;

    @RequestMapping(value = "URL", method = RequestMethod.POST)
    public ModelAndView controllerMethod(@ModelAttribute ModelAttribute reqModel, HttpServletRequest req, HttpServletResponse res) {

        try {
            response = self.executeService(param1, param2);

        } catch (Exception e) {

        }

    }
    public ResponseObject executeService(String param1, String param2){
        //Code....
    }
}

虽然我们的同事都给出了正确的答案,我总结一下。

在方面实现方面,spring 生成一个包装您的控制器的代理。代理的实现方式是它有特殊的钩子来调用 class 之前和之后的方面(或周围,完全改变流程)。

Spring 使用两种不同的代理生成策略:

  • java.lang.Proxy 基于
  • 基于 CGLIB

第一个通常更好、更快,但仅适用于接口。生成的代理是实现接口所有方法的“东西”。实现方法包含我之前讨论过的那些钩子,但由于这些方法只是接口中的方法,因此它们必须是 public

CGLIB - 速度较慢,但​​它也可以与 classes 一起使用(尽管有一些限制)。它的工作方式是子 class 父 class 并覆盖超级 class 提供的方法。这个新方法(我们称之为 foo)将调用所有挂钩,如果需要,代码中的某处将调用 super.foo().

现在,显然这不能真正用于私有方法,因为它不可能覆盖私有方法。 这就是为什么我的同事指出 private 在这里不起作用。

现在关于自我注射的东西:

当你在原始控制器的方法中并且你试图调用另一个方法(即使它 public),你不再使用代理,你很善良在代理后面并使用原始 class。所以这意味着您将无法利用“增强”方法。

这就是为什么会有自注入 - 你可以看到(例如使用调试器)自注入依赖实际上是对所有代理的依赖,这就是它开始工作的原因。

另一种解决方法是将方法重构为另一个 Spring bean,将此 bean 注入您的控制器,并为该 bean 提供定义。