我在控制器中写了下面的代码。
对于这个 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 方法之前执行方面。
答案 0 :(得分:0)
你需要@RequestMapping(value =“URL”,method = RequestMethod.POST)直接到 executeService然后它的工作。
答案 1 :(得分:0)
由于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....
}
}
答案 2 :(得分:0)
虽然我们的同事提供了正确的答案,但我会总结一下
当涉及方面实现时,spring会生成一个包装控制器的代理。 代理的实现方式是它具有特殊的钩子来调用类之前和之后的方面(或者围绕完全改变流程)。
Spring使用2种不同的代理生成策略:
第一个通常更好,更快,但仅适用于接口。生成的代理是实现接口所有方法的“东西”。实现方法包含我之前谈过的那些钩子,但由于这些方法只是接口中的方法,因此它们必须是public
CGLIB - 速度较慢,但它也适用于类(虽然有一些限制)。它的工作方式是子类化父类并重写超类提供的方法。这个新方法(让我们称之为 foo )将调用所有钩子和代码中的某个地方(如果需要)将调用super.foo()
。
现在,显然这对私有方法无效,因为它无法覆盖私有方法。
这就是为什么我的同事指出private
在这里不起作用。
现在关于自我注射的东西。
当你进入原始控制器的方法并且你试图只调用另一种方法时(即使它是公共的),你不再使用代理了,你有点落后于代理并使用原班。 所以这意味着你将无法利用“增强”方法。 这就是自我注入的原因 - 你可以看到(例如调试器)自注入依赖实际上是所有代理的依赖,这就是它开始工作的原因。
另一种解决方法是将该方法重构为另一个spring bean,将此bean注入您的控制器并为该bean提供定义
希望这有助于了解事情在幕后的工作原理