使用aop方式打印日志

当使用aop方式打印日志时,使用@annotation的方式,如:

@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping) || @annotation(org.springframework.web.bind.annotation.GetMapping) || @annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void log() {
}

如果Controller类有继承关系,如:

public interface BaseController {

    @GetMapping("/get")
    String get(@RequestParam String name, @RequestParam Integer age);

    @RequestMapping("/map")
    String map(@RequestParam String name);

}

@RestController
@RequestMapping("/demo")
@Slf4j
public class DemoController implements BaseController {

    @PostMapping("/post")
    public Resp post(@RequestBody @Validated Req req) {
        log.info("post");
        Resp resp = new Resp();
        return resp;
    }

    @Override
    public String get(@RequestParam String name, @RequestParam Integer age) {
        log.info("get");
        return "Hello World, name=" + name + ", age=" + age;
    }

    @Override
    public String map(@RequestParam String name) {
        log.info("map");
        return name;
    }
}

使用@annotation的方式只能拦截到/demo/post请求,不能拦截到/demo/get/demo/map,即在BaseController类中指定的路径不能拦截,如何解决呢?

阅读 1.4k
1 个回答

首先来说解决办法,

删除 DemoController 中的 get 方法和 map 方法,然后在BaseController中定义方法的默认实现,需要JDK8以上,例如:

    @GetMapping("/get")
    default String get(@RequestParam String name, @RequestParam Integer age){
        return "Hello World, name=" + name + ", age=" + age;
    }

然后运行代码,你会发现是有进你的切面的。

现在来说为什么会这样

对于你的这个切面来说,重点在于实现类上的方法有没有@XXXMapping这个注解,所以问题在于Java的继承和实现对于注解来说,关系是怎么样的。推荐你看这篇博客:子类上是否可以继承父类的注解
这里引用那篇博客的总结

1、父类某个方法上有注解(不论这个注解是否使用了inherit元注解标注),方法被继承后,只要不重写,那么也相当于这个注解被继承。。。其实这注解不算被继承,只不过是效果和继承一样,因为子类实例调用继承自父类的方法是使用super.父类方法的方式调用的,只不过默认省去super而已,所以最终调用的还是父类的方法,所以注解还是生效。。。而如果子类重写了父类的方法之后,那么调用该方法时就不会再调用到父类的方法中去了,所以此时注解就不会生效
2、在类上的注解,只有被标注了@Inherit元注解之后才会被子类继承。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进