首先,我使用ExceptionHandlers对RestController进行编码,一切运行良好。当我添加一个包含@RequestMapping(使用@Around)的建议时,它破坏了我的ExceptionHandler。抛出异常时例如,TypeMisMatchException,突然之间,我的控制器丢失了自动装配的bean(所有这些都是null)。 我在@PostConstruct中添加了一个检查,看到我的控制器实际上连接了bean。
MyRestContoller:
@RestController
@ControllerAdvice
public class MyRestController implements MyRestControllerInterface<Throwable> {
@Autowired private ApplicationContext applicationContext;
@Autowired private FirstBean firstBean;
@Autowired private SecondBean secondBean;
@PostConstruct
private void init() {
//just to print that beans are auto wired properly
//All beans are ok
}
@RequestMapping(value=“/”, method=RequestMethod.POST)
public ResponseEntity<String> postData(@SuppressWarnings("unused") @PathVariable ValidVersion version, @RequestBody DataRequest dataRequest) throws Throwable {
//stuff
return new ResponseEntity<>(newObj, HttpStatus.CREATED);
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Throwable.class)
private ErrorInfo handleBadRequest(HttpServletRequest req, Exception e) {
log.error("Error serving URL '" + req.getRequestURL()+ "': ", e);
//do something with firstBean
//but if thrown with configured advice the firstBean is null,
//and secondBean and applicationContext...
//
return new ErrorInfo(ErrorCodes.InternalServerError, req.getRequestURL().toString(), null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
我的观点:
@Service
@Aspect
public class SomeAspect {
@Autowired private GraphiteBeanReporter graphiteBeanReporter;
@Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")
public void restController() {}
@Pointcut("execution(* com.sample.MyRestController.*(..))")
public void methodPointcut() {}
@Around("restController() && methodPointcut()")
public Object whatToDoAround(ProceedingJoinPoint joinPoint) throws Throwable {
String metricName = joinPoint.getSignature().getName();
log.trace("inside the aspect of method '{}', metricName);
Context time = graphiteBeanReporter.initAndStartTimerMetic(metricName);
try {
Object result = joinPoint.proceed();
return result;
} finally {
if (time != null)
time.stop();
}
}
只是为了添加更多信息 MyRestController和SomeAspect bean在MVCCOnfig.class中配置 而在AppConfig.class中配置其他业务逻辑bean(即FirstBean,SecondBean等) 我的初始化器:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
public WebAppInitializer() {
// stuff
}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class, AppConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MVCConfig.class };
}
}
修改 添加了whatToDoAround建议的实现。它基本上是使用自动装配的bean向Graphite服务器报告指标(&#39;计时器&#39;)。正如我所提到的,如果控制器中没有抛出异常,则会按预期报告度量标准。
更新 -
具体而言,ValidVersion
是表示我的API有效版本的枚举。在url @PathVariable
中设置了未知字符串(无法转换为枚举值的字符串),抛出异常。此例外不会触发我的任何建议。我甚至尝试使用@AfterThrowing
但没有任何成功。