);
initThemeResolver(context);
initHandlerMappings(context);
//请求处理的adapter
initHandlerAdapters(context);
// 异常响应处理的resolver
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
// ......
}
3.1@initBinder和@ModelAttribute的作用原理
@initBinder和@ModelAttribute都是请求过程中的处理,我们知道springMvc通过HandlerApapter定位到具体的方法进行请求处理,因此查看HandlerHaper的实现类,发现RequestMappingHandlerAdapter比较符合我们的目标
点进去RequestMappingHandlerAdapter后发现里面的一个方法如下
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
// 这里会添加ResponseBody advice beans
initControllerAdviceCache();
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
// 这里找到contollerAdvice注解的类,缓存里面的方法
private void initControllerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
// 找到@ControllerAdvice注解标注的类
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
// 找到所有ModelAttribute标注的方法进行缓存,就可以使用了
Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
}
// 找到所有initBinder注解标注的方法进行缓存,就可以使用了
Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(adviceBean, binderMethods);
}
if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
}
}
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
}
// ......日志处理
}
3.2@ExceptionHandler注解的作用原理
相同的思路,@ExceptionHandler是响应时的处理,因此需要找到对应的Resolver,进入initHandlerExceptionResolvers(context)方法,
属性填充后会进行afterPropertiesSet方法,这个方法可以用在一些特殊情况中,也就是某个对象的某个属性需要经过外界得到,比如说查询数据库等方式,这时候可以用到spring的该特性,只需要实现InitializingBean。
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBodyAdvice beans
initExceptionHandlerAdviceCache();
if (this.argumentResolv