springmvc-原始碼除錯-3.3-initHandlerAdapters

森林猿發表於2020-10-20

initHandlerAdapters

初始化 HandlerAdapters 處理器介面卡 ,這裡上個文章分析過就不分析了…

private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;
    // 該值預設為 true 但是可以設定為 false
    // 如果設定為 false 那  Spring MVC就只會查詢名為“handlerMapping”的bean,並作為當前系統的唯一的HandlerMapping
    // 如果是 ture 則查詢所有的..
    if (this.detectAllHandlerAdapters) {
        //在ApplicationContext中查詢所有handler對映,包括父類上下文。
        Map<String, HandlerAdapter> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        //如果不為空
        if (!matchingBeans.isEmpty()) {
            // 轉換成集合
            this.handlerAdapters = new ArrayList<>(matchingBeans.values());
            // 排序
            AnnotationAwareOrderComparator.sort(this.handlerAdapters);
        }
    }
    else {
        try {
            // 從容器中獲取 HandlerAdapter ,如果獲取不到 下面則會新增預設的..
            HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
            this.handlerAdapters = Collections.singletonList(ha);
        }
        catch (NoSuchBeanDefinitionException ex) {
            //稍後就會建立一個預設的~~~
        }
    }

    //通過註冊,確保至少有一個 HandlerAdapter
    //如果找不到其他對映,則為預設的 HandlerAdapter。
    if (this.handlerAdapters == null) {
        this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
                         "': using default strategies from DispatcherServlet.properties");
        }
    }
}

簡答的說 就是根據 策略會初始化

org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,
org.springframework.web.servlet.function.support.HandlerFunctionAdapter

HttpRequestHandlerAdapter

這個類倒是沒那麼複雜… 初始化也沒做什麼事情… 不深究…

SimpleControllerHandlerAdapter

這個類倒是沒那麼複雜… 初始化也沒做什麼事情… 不深究…

RequestMappingHandlerAdapter

image-20201020134809668

這裡需要深究. InitializingBeanApplicationContextAware上文介紹過,這裡時機被回撥.

ApplicationContextAware這裡並不詳細說明… 並沒有做什麼事情

主要深究InitializingBean

afterPropertiesSet

	@Override
	public void afterPropertiesSet() {
		//
		initControllerAdviceCache();
        // 如果解析器為空
		if (this.argumentResolvers == null) {
		    // 獲取預設的解析器
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
        // 處理 @initBinder 引數解析器
		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() {
		if (getApplicationContext() == null) {
			return;
		}

		//獲取 所有的 @ControllerAdvice 註解 並且將其包裝成 ControllerAdviceBean
        // 簡單來說 @Controller 增強器.. 比如定義 統一反參之類的..
		List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());

		List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
            // 迴圈所有的 ControllerAdviceBean
		for (ControllerAdviceBean adviceBean : adviceBeans) {
		    // 獲取 Class
			Class<?> beanType = adviceBean.getBeanType();
			if (beanType == null) {
				throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
			}
			// 獲取 所有 不存在 @RequestMapping 但是存在 @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);
			}
			// 判斷是不是 RequestBodyAdvice 或者 ResponseBodyAdvice 子類
			if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
				requestResponseBodyAdviceBeans.add(adviceBean);
			}
		}

		if (!requestResponseBodyAdviceBeans.isEmpty()) {
			this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
		}

		if (logger.isDebugEnabled()) {
			int modelSize = this.modelAttributeAdviceCache.size();
			int binderSize = this.initBinderAdviceCache.size();
			int reqCount = getBodyAdviceCount(RequestBodyAdvice.class);
			int resCount = getBodyAdviceCount(ResponseBodyAdvice.class);
			if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) {
				logger.debug("ControllerAdvice beans: none");
			}
			else {
				logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize +
						" @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice");
			}
		}
	}

getDefaultArgumentResolvers

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

		//基於註釋的引數解析
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		resolvers.add(new PathVariableMethodArgumentResolver());
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		resolvers.add(new ServletModelAttributeMethodProcessor(false));
		resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new RequestHeaderMapMethodArgumentResolver());
		resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		resolvers.add(new RequestAttributeMethodArgumentResolver());

		// 基於型別的引數解析
		resolvers.add(new ServletRequestMethodArgumentResolver());
		resolvers.add(new ServletResponseMethodArgumentResolver());
		resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RedirectAttributesMethodArgumentResolver());
		resolvers.add(new ModelMethodProcessor());
		resolvers.add(new MapMethodProcessor());
		resolvers.add(new ErrorsMethodArgumentResolver());
		resolvers.add(new SessionStatusMethodArgumentResolver());
		resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

		// 自定義引數
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

		// Catch-all
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
		resolvers.add(new ServletModelAttributeMethodProcessor(true));

		return resolvers;
	}

getDefaultInitBinderArgumentResolvers

//跟上面差不多

getDefaultReturnValueHandlers

//跟上面差不多

HandlerFunctionAdapter

初始化也沒做啥東西…

相關文章