springmvc-原始碼除錯-3.3-initHandlerAdapters
文章目錄
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
這裡需要深究. InitializingBean
和ApplicationContextAware
上文介紹過,這裡時機被回撥.
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
初始化也沒做啥東西…
相關文章
- Javac 原始碼除錯教程Java原始碼除錯
- Node.js 原始碼除錯Node.js原始碼除錯
- 怎麼閱讀原始碼【除錯觀察原始碼】原始碼除錯
- samba原始碼安裝及除錯Samba原始碼除錯
- 如何斷點除錯Tomcat原始碼斷點除錯Tomcat原始碼
- 【Visual Leak Detector】原始碼除錯 VLD 庫原始碼除錯
- 編譯除錯Net6原始碼編譯除錯原始碼
- 【譯】使用 Visual Studio 除錯外部原始碼除錯原始碼
- 如何在Visual Studio中除錯.NET原始碼除錯原始碼
- RocketMQ系列-搭建Namesrv原始碼除錯環境MQ原始碼除錯
- Idea除錯Rocketmq原始碼編譯執行Idea除錯MQ原始碼編譯
- Mac 下使用 clion 除錯 PHP 核心原始碼Mac除錯PHP原始碼
- 程式設計技巧 --- VS如何除錯.Net原始碼程式設計除錯原始碼
- 使用 Chrome 除錯 Vue3 的 TypeScript 原始碼Chrome除錯VueTypeScript原始碼
- 【曹工雜談】Maven原始碼除錯工程搭建Maven原始碼除錯
- 根據除錯工具看Vue原始碼之watch除錯Vue原始碼
- Spark原始碼編譯與匯入IDEA除錯Spark原始碼編譯Idea除錯
- Python 程式碼除錯—使用 pdb 除錯Python除錯
- cesium原始碼編譯除錯及呼叫全過程原始碼編譯除錯
- Redis原始碼漂流記(二)-搭建Redis除錯環境Redis原始碼除錯
- NgRx Store createSelector 的單步除錯和原始碼分析除錯原始碼
- 讓你釋出的nuget包支援原始碼除錯原始碼除錯
- 根據除錯工具看Vue原始碼之computed(二)除錯Vue原始碼
- Android FrameWork學習(二)Android系統原始碼除錯AndroidFramework原始碼除錯
- JVM 原始碼分析(二):搭建 JDK 8 原始碼除錯環境(Windows 上使用 CLion)JVM原始碼JDK除錯Windows
- GDB 除錯程式碼除錯
- 根據除錯工具看原始碼之虛擬dom(一)除錯原始碼
- 鏈路追蹤 SkyWalking 原始碼分析 —— 除錯環境搭建原始碼除錯
- GDB 除錯 Mysql 實戰(一)原始碼編譯安裝除錯MySql原始碼編譯
- 直播平臺原始碼,JavaScript 的四種除錯輸出方式原始碼JavaScript除錯
- 原始碼都沒除錯過,怎麼能說熟悉 redis 呢?原始碼除錯Redis
- 根據除錯工具看Vue原始碼之虛擬dom(二)除錯Vue原始碼
- 輕鬆兩步,搭建斷點除錯 PHP 原始碼環境斷點除錯PHP原始碼
- 根據除錯工具看Vue原始碼之元件通訊(一)除錯Vue原始碼元件
- 訊息中介軟體 RocketMQ 原始碼解析 —— 除錯環境搭建MQ原始碼除錯
- 訊息中介軟體RocketMQ原始碼解析-- --除錯環境搭建MQ原始碼除錯
- SpringMVC-整合SSMSpringMVCSSM
- bashdb除錯bash指令碼除錯指令碼