在添加@Around建议和异常时,会丢失@controller中的应用程序上下文

时间:2015-12-01 19:57:58

标签: java spring spring-mvc autowired spring-aop

首先,我使用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但没有任何成功。

0 个答案:

没有答案