HandlerAdapter
直译就是Handler的适配器,主要的作用就是真正去执行Handler里面包含的的逻辑,
其中3个方法:
boolean supports(Object handler); 该是适配器是否适用于传入的Handler
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler);执行handler的逻辑,返回其对应的ModelAndView
long getLastModified(HttpServletRequest request, Object handler); 包装方法,返回lastModified时间
AbstractHandlerMethodAdapter
- 这个类实现了HandlerAdapter:其中supports方法初步判断传进来的Handler是否是HandlerMethod,然后其余的逻辑交给子类的钩子方法。
- 实现了Ordered接口:因为AbstractHandlerMethodAdapter可能在spring上下文中有多个。
- 继承了WebContentGenerator类:????
RequestMappingHandlerAdapter
这个Adapter是HandlerAdapter组件真正干大事的那个类。
此类的代码分为2部分。
- 从InitializingBean接口继承的afterPropertiesSet方法完成一些初始化工作。
- handlerInternal作为父类的handle方法被调用时,真正干活的那个方法。
先说第一部分,初始化的工作:afterPropertiesSet方法,来自于InitializingBean接口,会在此类被初始化为Bean后执行。
@Override
public void afterPropertiesSet() {
//initControllerAdviceCache。如其名字暗示的一样,此方法的主要作用是在初始化@ControllerAdvice相关的配置
// Do this first, it may add 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);
}
}
- initControllerAdviceCache。如其名字暗示的一样,此方法的主要作用是在初始化@ControllerAdvice相关的配置
private void initControllerAdviceCache() {
//先拿到ApplicationContext
if (getApplicationContext() == null) {
return;
}
//info记录是在哪个ApplicationContext中找@ControllerAdvice的
if (logger.isInfoEnabled()) {
logger.info("Looking for @ControllerAdvice: " + getApplicationContext());
}
//从上下文中取出所有被@ControllerAdvice标记的bean,封装为ControllerAdviceBean的List。
//这里使用的是ControllerAdviceBean的一个构造器方法,通过传入ApplicationContext,去遍历上下文中的所有带有@ControllerAdvice注解的bean
//ControllerAdviceBean保存了被注解的类的一些原始信息,比如@ControllerAdvice的扫描范围,是否有@Order排序注解等等
List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
//将取出的ControllerAdviceBean按Order信息排序一遍
AnnotationAwareOrderComparator.sort(beans);
List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>();
//遍历取出来的ControllerAdviceBean,做了3件事
for (ControllerAdviceBean bean : beans) {
//第一件事是找出其中的@ModelAtrribute标记的方法,放入成员变量modelAttributeAdviceCache
Set<Method> attrMethods = MethodIntrospector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(bean, attrMethods);
if (logger.isInfoEnabled()) {
logger.info("Detected @ModelAttribute methods in " + bean);
}
}
//第二件事是找出其中的@InitBinder标记的方法,放入成员变量initBinderAdviceCache
Set<Method> binderMethods = MethodIntrospector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(bean, binderMethods);
if (logger.isInfoEnabled()) {
logger.info("Detected @InitBinder methods in " + bean);
}
}
//第三件事是判断这些ControllerAdviceBean是否是RequestBodyAdvice||ResponseBodyAdvice的子类,放入成员变量requestResponseBodyAdvice
if (RequestBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
requestResponseBodyAdviceBeans.add(bean);
if (logger.isInfoEnabled()) {
logger.info("Detected RequestBodyAdvice bean in " + bean);
}
}
if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
requestResponseBodyAdviceBeans.add(bean);
if (logger.isInfoEnabled()) {
logger.info("Detected ResponseBodyAdvice bean in " + bean);
}
}
}
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
}
所以initControllerAdviceCache这个方法里初始化了3个成员变量
- modelAttributeAdviceCache : 保存ControllerAdvice中的ModelAttribute方法
- initBinderAdviceCache:保存ControllerAdvice中的initBinder方法
- requestResponseBodyAdvice: 保存ControllerAdvice中继承于RequestBodyAdvice||ResponseBodyAdvice的方法
这就是initControllerAdvice方法的全部逻辑。
接着回到afterPropertiesSet方法中。基础初始化了3个成员变量
argumentResolvers,initBinderArgumentResolvers,returnValueHandlers
这3个成员变量没有被初始化的话,赋予默认值
argumentResolvers:用于给处理器方法和注释了@ModelAttribute的方法设置参数。
initBinderArgumentResolvers:用于给注释了@initBinder的方法设置参数。
returnValueHandlers:用于将处理器的返回值处理成ModelAndView的类型。
所以在afterPropertiesSet方法中总共初始化了6个成员变量待用。
第二部分,被调用的时候的handleInternal方法,来自于父类的模板方法
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
//检查我们当前Adapter是否支持此request(方法和session),否则抛出异常
checkRequest(request);
//(同步或者不锁定)调用invokeHandlerMethod,得到ModelAndView这结果
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
其中的invokeHandlerMethod方法
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//将传入的request,response封装为ServletWebRequest
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
//创建WebDataBinderFactory,里面包含了initBinderAdviceCache和handlerMethod自己包含的initBinder
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
//还是同样的套路创建包含了ModelAttribute方法的ModelFactory
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//通过HandlerMethod创建包装类ServletInvocableHandlerMethod,塞入相关的成员变量待用
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
//创建ModelAndViewContainer
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
1.1 第一步
1.2 第二步,将HandlerMethod和WebBinderFactory创建ModelFactory
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
//通过handlerMethod创建相应的SessionAttributesHandler,阅读getSessionAttributesHandler里面的代码可以知道,
//主要是查找HandlerType上是否有@SessionAttribute的注解,创建对应的SessionAttributesHandler,
//并将创建的SessionAttributesHandler放入属性变量sessionAttributesHandlerCache。
//SessionAttributesHandler主要是封装handlerMethod带来的相关Session信息,
//SessionAttributeStore是SessionAttributesHandler用来存放session信息的地方,从代码可以看出,其实就是放入Request对应的session。为啥这样绕呢?大概是为了解耦可以放到其他地方。
SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
//第二步将modelAttributeAdviceCache中存放的ModelAttribute的方法(从@ControllerAdvice中提取出来的) 。
//创建InvocableHandlerMethod,里面包含了WebDataBinderFactory,HandlerMethod,ModelAttribute的方法,
//和成员变量argumentResolvers,parameterNameDiscoverer
Class<?> handlerType = handlerMethod.getBeanType();
Set<Method> methods = this.modelAttributeCache.get(handlerType);
if (methods == null) {
methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
this.modelAttributeCache.put(handlerType, methods);
}
List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>();
// Global methods first
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {
if (entry.getKey().isApplicableToBeanType(handlerType)) {
Object bean = entry.getKey().resolveBean();
for (Method method : entry.getValue()) {
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
}
}
//第三步将此HandlerMethod上私有的ModelAttribute的方法同理创建InvocableHandlerMethod,合并放入attrMethods
for (Method method : methods) {
Object bean = handlerMethod.getBean();
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
//第四步 创建ModelFactory,包含以下3种组件
//ModelAttribute的方法list,
//WebDataBinderFactory,
//SessionAttributesHandler(HandlerMethod上@SessionAttribute的想关信息)
return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
}
1.3 第三步 创建ModelAndViewContainer
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
//把request里面的INPUT_FLASH_MAP_ATTRIBUTE属性取出来放入
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
//将HandlMethod中相关的ModelAttribute和SessionAttribute的属性提前设置与mavContainer里面的Model中
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
//设置在Request重定向的时候是否使用DefaulModel
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
1.4 第四步 异步处理
1.5 第五步 真正调用HandlerMethod的方法
invocableMethod.invokeAndHandle(webRequest, mavContainer);
ModelAndViewContainer
其中并没有太过复杂的逻辑,如名字暗示的一样,它主要是作为一些属性的容器而存在的,那到底有些什么属性呢?
private boolean ignoreDefaultModelOnRedirect = false;
//视图,可以是任何类型
private Object view;
//存储想输入页面的属性,本质是LinkedHashMap的一种扩展
private final ModelMap defaultModel = new BindingAwareModelMap();
//redirect????
private ModelMap redirectModel;
//????
private boolean redirectModelScenario = false;
/* Names of attributes with binding disabled */
private final Set<String> bindingDisabledAttributes = new HashSet<String>(4);
private HttpStatus status;
private final SessionStatus sessionStatus = new SimpleSessionStatus();
private boolean requestHandled = false;
网友评论