spring aop 建议控制器失败

spring aop advice controller failed

控制器:

@Slf4j
@Controller
@RequestMapping("rest/test/api")
public class TestApiController {

    private LogApiService logApiService;
    private LogApiController logApiController;
    public TestApiController(LogApiService las, LogApiController lac) {
        this.logApiService = las;
        this.logApiController = lac;
    }

    @RequestMapping(value="", produces = MediaType.APPLICATION_JSON_VALUE)
    private ResponseEntity config(@RequestBody LogConfigDTO dto) {
        return logApiController.config(dto);
    }

看点:

@Slf4j
@Component
@Aspect
public class TestApiControllerAop {

    private ApiProperties apiProperties;

    public TestApiControllerAop(ApiProperties apiProperties) {
        this.apiProperties = apiProperties;
    }

    @Before("execution(* com.demo.TestApiController.*(..)) " +
        "&& @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void beforeRequestMappingAnnotatedMethod() {
        boolean isDebug = apiProperties.getLog().isDebug();
        log.info("debug flag is" + isDebug);
        if (!isDebug) {
            throw new RuntimeException("test api controller debug mode is turned off");
        }
    }
}

结果:本应注入的 beans 但失败了,LogApiServiceLogApiController 对象均为空。此外,@Before方法没有运行。虽然我可以看到 TestApiController 被标记为 EnhancerBySpringCGLIB

问题是控制器中的私有访问级别!将其更改为 public 即可解决问题。 applicationContext.getBean(xx.class) 会显示

这正是它在 pointcut 目标方法是 private 时的解释方式:所有注入的字段都是空的。我猜这是因为当它是私有的时候,controller bean 是从和 applicationContext.getBean() 相同的地方取出的,而当它是 public 的时候,controller bean 是不同的。我刚刚用

试过了
@GetMapping("get")
private void get() {
    log.info("");
}

它不是针对切入点的,但它看到的与图片相同。 Controller就像Service,被调用的时候,通常是一个public方法,就像一个规则。另一方面,也可以从浏览器调用控制器私有方法,使这个规则"broken"。结论是无论一个方法是不是aop对象,如果能通过浏览器调用,那一定是public方法