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 但失败了,LogApiService
和 LogApiController
对象均为空。此外,@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方法
控制器:
@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 但失败了,LogApiService
和 LogApiController
对象均为空。此外,@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方法