最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?WebMVC初始化Controller流程詳解

 更新時(shí)間:2022年02月22日 10:11:18   作者:擬夢(mèng)  
這篇文章主要介紹了Spring?WebMVC初始化Controller流程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring WebMVC初始化Controller流程

此篇文章開(kāi)始之前先向大家介紹一個(gè)接口 InitializingBean

這個(gè)接口的作用如果了解spring生命周期的應(yīng)該知道 ,這個(gè)接口的作用就是在bean初始化之后會(huì)執(zhí)行的init方法

public interface InitializingBean {
? ? void afterPropertiesSet() throws Exception;
}

當(dāng)然能實(shí)現(xiàn)這種方式的方法spring還介紹了關(guān)于注解的@PostConstruct 和xml 的 init-method = "" 的兩種方式。但是springmvc使用的是接口的方式。

這里要介紹的初始化Controller是指填充完HandlerMapping map<String,Method>即代表初始化Controller流程

我們?cè)偬嵋稽c(diǎn)小知識(shí)。聲明一個(gè)controller類(lèi)有哪些方式。(現(xiàn)在應(yīng)該沒(méi)有人用第二/三種方式吧)

  • 1.使用注解@Controller 和 請(qǐng)求路徑@RequestMapping
  • 2.實(shí)現(xiàn) Controller 接口 并將該類(lèi)交給spring容器管理beanName為請(qǐng)求路徑
  • 3.實(shí)現(xiàn) HttpRequestHandler 接口并將該類(lèi)交給spring容器管理beanName為請(qǐng)求路徑

那么我們的map填充就從實(shí)現(xiàn)了InitializingBean 接口 的afterPropertiesSet這個(gè)方法開(kāi)始。

源碼中是這個(gè)類(lèi) AbstractHandlerMethodMapping(下面的代碼有刪減)

public void afterPropertiesSet() {
? ? this.initHandlerMethods();
}
protected void initHandlerMethods() {
? ? String[] var1 = this.getCandidateBeanNames();//1.獲取容器初始化的所有beanName
? ? int var2 = var1.length;
? ? for(int var3 = 0; var3 < var2; ++var3) {
? ? ? ? String beanName = var1[var3];
? ? ? ? if (!beanName.startsWith("scopedTarget.")) {
? ? ? ? ? ? this.processCandidateBean(beanName);//2.獲取所有聲明為Controller類(lèi)的beanName
? ? ? ? }
? ? }
? ? this.handlerMethodsInitialized(this.getHandlerMethods());
}

獲取容器初始化的所有beanName(父子容器概念)

protected String[] getCandidateBeanNames() {
? ? return this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.obtainApplicationContext(), Object.class) : this.obtainApplicationContext().getBeanNamesForType(Object.class);
}

獲取所有聲明為Controller類(lèi)的beanName

protected void processCandidateBean(String beanName) {
? ? Class beanType = null;
? ? try {
? ? ? ? beanType = this.obtainApplicationContext().getType(beanName);//獲取bean的類(lèi)型
? ? } catch (Throwable var4) {
? ? ? ? if (this.logger.isTraceEnabled()) {
? ? ? ? ? ? this.logger.trace("Could not resolve type for bean '" + beanName + "'", var4);
? ? ? ? }
? ? }
? ? if (beanType != null && this.isHandler(beanType)) {//獲取所有聲明為Controller類(lèi)的beanName
? ? ? ? this.detectHandlerMethods(beanName);//1.開(kāi)始處理這種類(lèi)型的beanName
? ? }
}

開(kāi)始處理這種類(lèi)型的beanName

protected void detectHandlerMethods(Object handler) {
? ? Class<?> handlerType = handler instanceof String ? this.obtainApplicationContext().getType((String)handler) : handler.getClass();
? ? if (handlerType != null) {
? ? ? ? Class<?> userType = ClassUtils.getUserClass(handlerType);
? ? ? ? Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (method) -> {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? return this.getMappingForMethod(method, userType);//1.獲取到類(lèi)類(lèi)型下所有的方法
? ? ? ? ? ? } catch (Throwable var4) {
? ? ? ? ? ? ? ? throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, var4);
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? if (this.logger.isTraceEnabled()) {
? ? ? ? ? ? this.logger.trace(this.formatMappings(userType, methods));
? ? ? ? }
? ? ? ? methods.forEach((method, mapping) -> {
? ? ? ? ? ? Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
? ? ? ? ? ? this.registerHandlerMethod(handler, invocableMethod, mapping);//注冊(cè)并填充map
? ? ? ? });
? ? }
}

獲取到類(lèi)類(lèi)型下所有的方法和注冊(cè)并填充map

第一個(gè) MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap();

urlLookup.add(url, mapping);
eg:url = '/test/test.do'?

mapping是一個(gè)RequestMappingInfo 對(duì)象 RequestMappingInfo.patternsCondition = T --> /test/test.do

第二個(gè) Map<T, AbstractHandlerMethodMapping.MappingRegistration<T>> registry = new HashMap();

eg:key = 'url' ?value = 'method'

而我們的第二種和第三種的方式基本沒(méi)有用了,因?yàn)闀?huì)出現(xiàn)類(lèi)爆炸,就像原始的servlet一樣每一個(gè)方法都需要寫(xiě)一個(gè)類(lèi)。

這兩種方式是通過(guò)beanName為路徑來(lái)實(shí)例化對(duì)象并執(zhí)行通過(guò)該對(duì)象來(lái)執(zhí)行里面的方法的。

源碼中這兩種map的填充方式是在bean的生命周期中通過(guò)實(shí)現(xiàn)beanFactory的applyBeanPostProcessorsBeforeInitialization方法來(lái)填充的。 

@Controller 類(lèi)中初始化問(wèn)題

在Controller類(lèi)中常常遇到有些參數(shù)需要初始化,甚至有些只允許初始化一次,而Controller類(lèi)不像servelet類(lèi)可以調(diào)用init()函數(shù)進(jìn)行初始化,這里想到的辦法是設(shè)置標(biāo)記值,讓初始化部分只調(diào)用一次。

第一種方法

設(shè)置isStart值。

private static Boolean isStart = false;
if(!isStart){
  //進(jìn)行初始化
  isStart=true;
}

第二種方法

使用注釋@PostConstruct,該注釋的類(lèi)會(huì)在類(lèi)初始化時(shí)進(jìn)行調(diào)用。

@PostConstruct
private void init(){
//進(jìn)行初始化
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring?@EventListener?異步中使用condition的問(wèn)題及處理

    Spring?@EventListener?異步中使用condition的問(wèn)題及處理

    這篇文章主要介紹了Spring?@EventListener?異步中使用condition的問(wèn)題及處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java實(shí)現(xiàn)的mysql事務(wù)處理操作示例

    Java實(shí)現(xiàn)的mysql事務(wù)處理操作示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的mysql事務(wù)處理操作,結(jié)合實(shí)例形式較為詳細(xì)的分析了Java基于JDBC操作mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)事務(wù)處理的相關(guān)概念、操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2018-08-08
  • 在CentOS上配置Java環(huán)境變量的教程

    在CentOS上配置Java環(huán)境變量的教程

    這篇文章主要介紹了在CentOS上配置Java環(huán)境變量的教程,同時(shí)適用于Fedora等其他RedHat系的Linux系統(tǒng),需要的朋友可以參考下
    2015-06-06
  • Java?中向?Arraylist?添加對(duì)象的示例代碼

    Java?中向?Arraylist?添加對(duì)象的示例代碼

    本文介紹了如何在 Java 中向 ArrayList 添加對(duì)象,并提供了示例和注意事項(xiàng),通過(guò)掌握這些知識(shí),讀者可以在自己的 Java 項(xiàng)目中有效地使用 ArrayList 來(lái)存儲(chǔ)和操作對(duì)象,需要的朋友可以參考下
    2023-11-11
  • 關(guān)于mybatis遇到Integer類(lèi)型的參數(shù)時(shí)動(dòng)態(tài)sql需要注意條件

    關(guān)于mybatis遇到Integer類(lèi)型的參數(shù)時(shí)動(dòng)態(tài)sql需要注意條件

    這篇文章主要介紹了關(guān)于mybatis遇到Integer類(lèi)型的參數(shù)時(shí)動(dòng)態(tài)sql需要注意條件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 詳解Springboot事務(wù)管理

    詳解Springboot事務(wù)管理

    本篇文章主要介紹了詳解Springboot事務(wù)管理,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • 詳解IDEA 中使用Maven創(chuàng)建項(xiàng)目常見(jiàn)錯(cuò)誤和使用技巧(推薦)

    詳解IDEA 中使用Maven創(chuàng)建項(xiàng)目常見(jiàn)錯(cuò)誤和使用技巧(推薦)

    這篇文章主要介紹了詳解IDEA 中使用Maven創(chuàng)建項(xiàng)目常見(jiàn)錯(cuò)誤和使用技巧(推薦),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Maven依賴(lài)沖突原因以及解決方法

    Maven依賴(lài)沖突原因以及解決方法

    依賴(lài)沖突是指項(xiàng)目依賴(lài)的某一個(gè) jar 包,有多個(gè)不同的版本,因而造成類(lèi)包版本沖突依賴(lài)沖突很經(jīng)常是類(lèi)包之間的間接依賴(lài)引起的,本文將給大家介紹Maven依賴(lài)沖突原因以及解決方法,需要的朋友可以參考下
    2023-12-12
  • 詳解MyBatis的Dao層實(shí)現(xiàn)和配置文件深入

    詳解MyBatis的Dao層實(shí)現(xiàn)和配置文件深入

    這篇文章主要為大家詳細(xì)介紹了MyBatis的Dao層實(shí)現(xiàn)和配置文件深入,文中的示例代碼講解詳細(xì),感興趣的小伙伴快來(lái)跟隨小編一起學(xué)習(xí)一下
    2022-07-07
  • java數(shù)組中的異常類(lèi)型整理

    java數(shù)組中的異常類(lèi)型整理

    在本篇文章里小編給各位分享的是一篇關(guān)于java數(shù)組中的異常類(lèi)型整理內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-02-02

最新評(píng)論

吕梁市| 鄂尔多斯市| 普格县| 涿州市| 刚察县| 汉沽区| 博客| 海原县| 九龙坡区| 综艺| 思南县| 南郑县| 沅江市| 安吉县| 永德县| 安吉县| 和政县| 左云县| 孝感市| 务川| 临汾市| 长沙市| 金阳县| 建始县| 英德市| 孟津县| 平湖市| 长丰县| 永宁县| 望奎县| 吐鲁番市| 邮箱| 尼勒克县| SHOW| 乌什县| 娄底市| 彰武县| 佛坪县| 万盛区| 灵石县| 晋中市|