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

Spring管理Controller可行性原理示例分析

 更新時間:2023年07月18日 09:45:34   作者:江南一點(diǎn)雨  
這篇文章主要為大家介紹了Spring管理Controller可行性原理示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Spring 容器中的父子容器

上篇文章和小伙伴們聊了 Spring 容器中的父子容器問題,也和小伙伴們梳理了 Spring 容器和 SpringMVC 容器之間的關(guān)系,其中,Spring 容器是父容器,SpringMVC 是子容器,子容器可以訪問父容器中的 Bean,但是父容器無法訪問子容器中的 Bean。

在一個 SSM 項(xiàng)目中,你可以單純使用 SpringMVC 容器,這個沒問題,項(xiàng)目可以正常運(yùn)行。但是,有的小伙伴可能要問了,如果把所有的 Bean 都掃描到 Spring 容器中行不行?

先來說結(jié)論:可以!但是需要額外配置。

閱讀本文需要先了解 Spring 容器的父子容器哦,如果還不了解的話建議先閱讀上篇文章。

為什么不能把所有 Bean 都注冊到 Spring 容器中呢?按照我們上篇文章中的分析,所有 Bean 都注冊到 Spring 容器之后,Spring 容器作為父容器,SpringMVC 作為子容器,按理說,由于子容器可以訪問父容器中的 Bean,所以 SpringMVC 是可以正常訪問 Spring 容器中的 Bean 的,所以,似乎把所有的 Bean 都掃描到 Spring 容器應(yīng)該是沒有問題的?

其實(shí)不然!

問題就出在 SpringMVC 容器查找 Controller 的方式上,SpringMVC 容器查找 Controller,默認(rèn)情況下,只在當(dāng)前容器中查找,并不會去父容器中查找,所以如果把 Controller 都掃描到父容器的話,對于 SpringMVC 來說,相當(dāng)于系統(tǒng)中就沒有 Controller 了,所以你一訪問,直接就 404 了。

接下來,我結(jié)合源碼和小伙伴們分析一下。

SpringMVC 如何查找 Controller 

首先,小伙伴們知道,在 SpringMVC 中,當(dāng)請求到達(dá)服務(wù)端之后,需要由處理器映射器 HandlerMapping 來確定這個請求應(yīng)該由哪個處理器來處理,所以,按理說,HandlerMapping 中就會記錄所有的處理器信息,也就是 Controller 的信息。一般我們在 SpringMVC 中使用的 HandlerMapping 都是 RequestMappingHandlerMapping,所以這里我們就通過 RequestMappingHandlerMapping 的初始化來看一下,SpringMVC 到底是如何查找 Controller 的。

在 RequestMappingHandlerMapping#afterPropertiesSet 方法中,調(diào)用了父類的 afterPropertiesSet 方法,我們來看下:

AbstractHandlerMethodMapping#afterPropertiesSet:

@Override
public void afterPropertiesSet() {
    initHandlerMethods();
}
protected void initHandlerMethods() {
    for (String beanName : getCandidateBeanNames()) {
        if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
            processCandidateBean(beanName);
        }
    }
    handlerMethodsInitialized(getHandlerMethods());
}

initHandlerMethods 方法就是初始化處理器的方法,也就是在這個方法中,去嘗試找到所有的 Controller,并且把每一個接口方法都封裝成 HandlerMethod 對象。

我們來看下 getCandidateBeanNames 方法,這個方法用來找到所有的候選的 Bean:

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

關(guān)鍵點(diǎn)就在這了,這里首先去判斷 detectHandlerMethodsInAncestorContexts 變量的值,如果這個變量為 true,則調(diào)用 BeanFactoryUtils.beanNamesForTypeIncludingAncestors 方法去查詢 Bean,這個方法在上篇文章中松哥和大家分享過,用來查找 Bean 的名稱,包括父容器中的 Bean 都會查找到并返回;

如果 detectHandlerMethodsInAncestorContexts 變量為 false,則調(diào)用 getBeanNamesForType 方法去查找 Bean,getBeanNamesForType 方法我們上篇文章也講過,這個方法只找當(dāng)前容器的 Bean,不會去父容器中查找。

SpringMVC 容器查找 Bean

所以現(xiàn)在問題的關(guān)鍵就在于 detectHandlerMethodsInAncestorContexts 變量了,這個變量默認(rèn)是 false,即,默認(rèn)情況下,只去當(dāng)前容器(SpringMVC 容器)查找 Bean。

這里找到的 beanName 是當(dāng)前容器中所有的 beanName,所以接下來還要去 processCandidateBean 方法走一圈,這個方法會去判斷這個 Bean 是否是一個 Controller,如果是就將之收集到一起:

protected void processCandidateBean(String beanName) {
    Class<?> beanType = null;
    beanType = obtainApplicationContext().getType(beanName);
    if (beanType != null && isHandler(beanType)) {
        detectHandlerMethods(beanName);
    }
}
@Override
protected boolean isHandler(Class<?> beanType) {
    return AnnotatedElementUtils.hasAnnotation(beanType, Controller.class);
}

可以看到,只有這類上有 @Controller 注解,這個類才會被留下來。

好啦,剩下的邏輯我們就不看了。

現(xiàn)在大家已經(jīng)了解到這樣一個情況:

SpringMVC 容器在初始化 HandlerMapping 的時候,會去查找所有的 Controller 并完成初始化,但是在默認(rèn)情況下,只會去當(dāng)前容器中查找,并不會去父容器中查找。

所以,如果把 Controller 讓 Spring 容器掃描并管理,那么就會導(dǎo)致在默認(rèn)情況下,SpringMVC 容器找不到 Controller,進(jìn)而導(dǎo)致所有的請求 404。

在前面的講解中,松哥都強(qiáng)調(diào)了默認(rèn)情況,意思就是說這個事情還有轉(zhuǎn)圜的余地,看了前面源碼的小伙伴應(yīng)該也發(fā)現(xiàn)了,只要我們把 detectHandlerMethodsInAncestorContexts 變量改為 true,那么 HandlerMapping 就會去父容器中查找 Bean,這樣即使被 Spring 容器掃描并管理的 Bean,也就能夠查找到了。

修改方式

spring-servlet.xml:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    <property name="detectHandlerMethodsInAncestorContexts" value="true"/>
</bean>

在 Spring 容器中直接掃描所有 Bean:

<context:component-scan base-package="org.javaboy.web"/>

web.xml 中加載這兩個配置文件:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-servlet.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

這樣配置之后,就可以把所有 Bean 都掃描到 Spring 容器中了。

好啦,今天這篇文章目的不是為了讓小伙伴們?nèi)ピ?Spring 容器中管理 Controller,只是想借這樣一個契機(jī),一起來捋一捋 SpringMVC 中 HanderMapping 的原理。

如果感覺本文閱讀有點(diǎn)吃力,可以先看看上篇文章

以上就是Spring管理Controller可行性原理示例分析的詳細(xì)內(nèi)容,更多關(guān)于Spring管理Controller的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java多線程之線程,進(jìn)程和Synchronized概念初解

    java多線程之線程,進(jìn)程和Synchronized概念初解

    這篇文章主要介紹了java多線程之線程,進(jìn)程和Synchronized概念初解,涉及進(jìn)程與線程的簡單概念,實(shí)現(xiàn)多線程的方式,線程安全問題,synchronized修飾符等相關(guān)內(nèi)容,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-11-11
  • Spring?使用注解存儲和讀取?Bean對象操作方法

    Spring?使用注解存儲和讀取?Bean對象操作方法

    在?Spring?中,要想更加簡單的實(shí)現(xiàn)對?Bean?對象的儲存和使用,其核心就是使用?注解?,本文主要就是演示如何使用注解實(shí)現(xiàn)對?Bean?對象的存取操作,感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • Springboot創(chuàng)建時常用的依賴詳解

    Springboot創(chuàng)建時常用的依賴詳解

    本文介紹了Spring?Boot項(xiàng)目中常用依賴的配置及作用,涵蓋了父依賴、Web應(yīng)用、測試、數(shù)據(jù)庫、MyBatis、連接池、JSON處理、Lombok、AOP、校驗(yàn)、監(jiān)控、工具包、打包配置、多配置文件以及熱部署等
    2025-03-03
  • SpringBoot如何使用Scala進(jìn)行開發(fā)的實(shí)現(xiàn)

    SpringBoot如何使用Scala進(jìn)行開發(fā)的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot如何使用Scala進(jìn)行開發(fā)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Spring?Boot?集成Redisson實(shí)現(xiàn)分布式鎖詳細(xì)案例

    Spring?Boot?集成Redisson實(shí)現(xiàn)分布式鎖詳細(xì)案例

    這篇文章主要介紹了Spring?Boot?集成Redisson實(shí)現(xiàn)分布式鎖詳細(xì)案例,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-08-08
  • 解決SecureRandom.getInstanceStrong()引發(fā)的線程阻塞問題

    解決SecureRandom.getInstanceStrong()引發(fā)的線程阻塞問題

    這篇文章主要介紹了解決SecureRandom.getInstanceStrong()引發(fā)的線程阻塞問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • SpringBoot對靜態(tài)資源的映射規(guī)則詳解

    SpringBoot對靜態(tài)資源的映射規(guī)則詳解

    在Web應(yīng)用中會涉及到大量的靜態(tài)資源,例如 JS、CSS和HTML等,我們知道,Spring MVC 導(dǎo)入靜態(tài)資源文件時,需要配置靜態(tài)資源的映射,但在 SpringBoot 中則不再需要進(jìn)行此項(xiàng)配置,因?yàn)镾pringBoot已經(jīng)默認(rèn)完成了這一工作,本文給大家介紹了SpringBoot對靜態(tài)資源的映射規(guī)則詳
    2024-12-12
  • 給@Value設(shè)置默認(rèn)值以及為static變量賦值問題

    給@Value設(shè)置默認(rèn)值以及為static變量賦值問題

    在Spring框架中,@Value注解用于屬性注入,可將配置文件中的值賦給變量,未指定默認(rèn)值時,若配置文件缺少相應(yīng)屬性,程序啟動會報(bào)錯,可通過設(shè)定默認(rèn)值防止此問題,對于靜態(tài)變量,由于@Value無法直接注入,需通過Set方法賦值,該方法也支持默認(rèn)值設(shè)置
    2024-09-09
  • Java中基于DeferredResult的異步服務(wù)詳解

    Java中基于DeferredResult的異步服務(wù)詳解

    這篇文章主要介紹了Java中基于DeferredResult的異步服務(wù)詳解,DeferredResult字面意思是"延遲結(jié)果",它允許Spring MVC收到請求后,立即釋放(歸還)容器線程,以便容器可以接收更多的外部請求,提升吞吐量,需要的朋友可以參考下
    2023-12-12
  • logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀

    logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀

    這篇文章主要為大家介紹了logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11

最新評論

台江县| 女性| 盐山县| 南平市| 射阳县| 长治市| 晴隆县| 岳普湖县| 潜山县| 霸州市| 石泉县| 怀集县| 南康市| 大丰市| 宜兰市| 阳江市| 图片| 茌平县| 中卫市| 旌德县| 斗六市| 蒙城县| 徐水县| 东乡县| 赤水市| 黔东| 长丰县| 永州市| 资阳市| 绩溪县| 安义县| 陆河县| 双流县| 琼结县| 汉沽区| 陈巴尔虎旗| 汾西县| 泰宁县| 信丰县| 德州市| 太康县|