Spring MVC和AOP:@Pointcuts仅适用于Rest控制器,不适用于常见的Web控制器

时间:2016-09-26 16:59:49

标签: spring-mvc aop spring-aop spring-aspects

我正在使用Spring Framework 4.3.3在网络环境中工作。

我通过@Controller使用Web Web Browser请求,该@Controller请求使用其他Rest的依赖关系,但用于@Service目的。后面提到的使用了Combining Data and Presentation Formats等......

这种关于“网络”的方法。使用休息'如何在Content Negotiation using Spring MVC部分中为Rest部分解释依赖关系。直到这里开发/测试和生产工作正常。这是一种有价值的方法。

注意 @Controller类使用ResponseEntity<?>进行注释,因为我使用了@ResponseBodyAOP

问题在于@Configuration @EnableAspectJAutoProxy public class AopConfig { }

关于我的基础设施:

@Controller

关于PersonaDeleteOneController我有这两个类:

  • deleteOne(@PathVariable String id, Model model)
      {li> @GetMapping deleteOne(@PathVariable String id, RedirectAttributes redirectAttributes) {li> @DeleteMapping PersonaRestController
  • deleteOne(@PathVariable String id)
      {li> @DeleteMapping com.manuel.jordan.controller.persona

这两个类在名为:

的同一个包中声明
  • @Pointcut

我有以下@Pointcut(value= "execution(* com.manuel.jordan.controller.*.*Controller.deleteOne(String, ..)) && args(id) && target(object)") public void deleteOnePointcut(String id, Object object){}

@Pointcut

@Before(value="ControllerPointcut.deleteOnePointcut(id, object)") public void beforeAdviceDeleteOne(String id, Object object){ logger.info("beforeAdviceDeleteOne - @Controller: {} - Method: deleteOne - id: {}", object.getClass().getSimpleName(), id); } 用于以下建议:

Rest

当我执行AOP + logging测试时,我可以通过@Controller确认打印出以下模式:

  • @Service休息) - &gt; @Repository - &gt; Web

直到这里所有的工作如何预期

当我执行AOP + logging测试时,我可以通过@Controller确认打印出以下模式:

  • @Service休息) - &gt; @Repository - &gt; @Controller

我需要或期望的是以下内容:

  • @Controller Web ) - &gt; @Service休息) - &gt; @Repository - &gt; deleteOne

有什么不对或丢失? @Controller @RequestMapping(value="/personas") public class PersonaDeleteOneController { private final PersonaRestController personaRestController; @Autowired public PersonaDeleteOneController(PersonaRestController personaRestController){ this.personaRestController = personaRestController; } @GetMapping(value="/delete/{id}", produces=MediaType.TEXT_HTML_VALUE) public String deleteOne(@PathVariable String id, Model model){ model.addAttribute(personaRestController.findOneById(id)); model.addAttribute("root", "/personas/delete"); return "persona/deleteOne"; } @DeleteMapping(value="/delete/{id}", produces=MediaType.TEXT_HTML_VALUE) public String deleteOne(@PathVariable String id, RedirectAttributes redirectAttributes){ personaRestController.deleteOne(id); redirectAttributes.addFlashAttribute("message", "process.successful"); return "redirect:/message"; } } 签名对其参数没有歧义。

生产的情况相同。

Alpha

控制器:

@Controller
@RequestMapping(value="/personas")
public class PersonaRestController {

    private final PersonaService personaService;

    @Autowired
    public PersonaRestController(PersonaService personaService){
        this.personaService = personaService;
    }

    @DeleteMapping(value="/{id}")
    public ResponseEntity<Void> deleteOne(@PathVariable String id){
        personaService.deleteOne(id);
        return ResponseEntity.noContent().build();
    }

    ....

this.

如何看待我不使用 Messenger.Default.Send(new NavigateToPageMessage() { Page = "/MasterDetail.DetaiPage" }); private void InitializeMessageInterception() { MessengerInstance.Register<NavigateToPageMessage>(this, OnNavigateToPage); } 来执行方法调用。

1 个答案:

答案 0 :(得分:1)

似乎问题在于pointcut定义。您可能会注意到您的建议方法仅针对具有一个参数的方法执行,因此这是因为您在切入点声明中指定了args(id)。如果删除args(id),它必须按预期工作,但在这种情况下,必须使用某些解决方法来公开参数值。

我认为这是AspectJ的奇怪行为,因为像execution(* *.*(String, ..)) && args(arg) && target(t))这样的结构具有明确的语义意义,可以使用String第一个参数捕获所有方法并将其公开给args。它至少可以成为AspectJ开发人员的错误或功能。

要获得您想要的内容,您可以使用joinPoint.getArgs()内部建议方法的解决方法,如下所示:

@Pointcut(value=
"execution(* com.manuel.jordan.controller.*.*Controller.deleteOne(..)) && target(object)")
public void deleteOnePointcut(Object object){}

@Before(value="ControllerPointcut.deleteOnePointcut(object)")
public void beforeAdviceDeleteOne(JoinPoint jp, Object object){
    Object id = jp.getArgs()[0];
    logger.info("beforeAdviceDeleteOne - @Controller: {} - Method: deleteOne - id: {}", object.getClass().getSimpleName(), id);
}