【Spring源码点滴】 @ControllerAdvice
在SpringMVC中,@Controller可以定义一个控制层Bean,其中的方法比较专注于业务,实际在应用中,通常需要对业务前后进行统一的处理,这时会告诉你可以用@ControllerAdvice注解,在其中可以完成统一处理的逻辑,那么@ControllerAdive是怎么实现的?
首先,根据@ControllerAdvice查找到和它相关的类,发现ControllerAdviceBean。
然后,发现方法findAnnotatedBeans,为静态方法,应该是初始化被调用,debug,启动应用,拦截下来,查看代码,基本逻辑就是从容器中查找@ControllerAdvice注解的Bean,然后new一个ControllerAdviceBean,放入List中返回给调用者。
【【Spring源码点滴】 @ControllerAdvice】调用者是谁?跟踪返回,来到RequestMappingHandlerAdapter.initControllerAdviceCache方法,在获取返回List之后,首先排序,然后遍历List。如果项目中有多个ControllerAdive,是需要排序的,可以实现Ordered接口,或者在类上面注解@Order,默认排序值为INT最大值,优先级最低。
阅读遍历的逻辑,会发现其实只是获取ControllerAdviceBean中的对应注解的方法,然后放入RequestMappingHandlerAdapter对应的缓存中,到这就明了了,这个统一处理的其实还是通过RequestMappingHandlerAdapter实现的,只是再抽象了一层MVC的模式,使开发者可以关注@ControllerAdvice注解的Bean本身。
有四种可被读取的方式,代码在最下方:
1.MODEL_ATTRIBUTE_METHODS,方法上注解RequestMapping或ModelAttribute;
2.INIT_BINDER_METHODS,方法上注解InitBinder;
3.继承RequestBodyAdvice;
4.继承ResponseBodyAdvice;
这4种方法分别有什么作用,网上的资料有很多,就不赘述了,本人偏向于分析设计思想。至于RequestMappingHandlerAdapter,放另一篇文章吧。
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
Set attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
if (logger.isInfoEnabled()) {
logger.info("Detected @ModelAttribute methods in " + adviceBean);
}
}
Set binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(adviceBean, binderMethods);
if (logger.isInfoEnabled()) {
logger.info("Detected @InitBinder methods in " + adviceBean);
}
}
if (RequestBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
if (logger.isInfoEnabled()) {
logger.info("Detected RequestBodyAdvice bean in " + adviceBean);
}
}
if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
if (logger.isInfoEnabled()) {
logger.info("Detected ResponseBodyAdvice bean in " + adviceBean);
}
}
}
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长