日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

boot spring 没有父子容器_Spring 系列(二):Spring MVC的父子容器

發(fā)布時(shí)間:2025/3/11 javascript 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 boot spring 没有父子容器_Spring 系列(二):Spring MVC的父子容器 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.背景

在使用Spring MVC時(shí)候大部分同學(xué)都會(huì)定義兩個(gè)配置文件,一個(gè)是Spring的配置文件spring.xml,另一個(gè)是Spring MVC的配置文件spring-mvc.xml。

在這里給大家拋個(gè)問題,如果在spring.xml和spring-mvc.xml文件中同時(shí)定義一個(gè)相同id的單例bean會(huì)怎樣呢?大家可以先思考一下再繼續(xù)往下看。

我做了個(gè)實(shí)驗(yàn),結(jié)論是:容器中會(huì)同時(shí)存在兩個(gè)相同id 的bean,而且使用起來互不干擾。

這是為什么呢?學(xué)過Spring的同學(xué)肯定會(huì)質(zhì)疑,眾所周知id是bean的唯一標(biāo)示,怎么可能同時(shí)存在兩個(gè)相同id的bean呢?是不是我在胡扯呢?

原諒我在這和大家賣了個(gè)關(guān)子,其實(shí)大家說的都沒錯(cuò),因?yàn)檫@里涉及到Spring MVC父子容器的知識(shí)點(diǎn)。

這個(gè)知識(shí)點(diǎn)是:在使用Spring MVC過程中會(huì)存在Spring MVC 、Spring兩個(gè)IOC容器,且Spring MVC是Spring的子容器。

那這個(gè)父子容器到底是什么呢?

為了保證我所說的權(quán)威性,而不是知識(shí)的二道販子,我將從Spring 官方文檔和源碼兩方面展開介紹。

2.Spring MVC父子容器

2.1 web.xml配置

還是先找程序入口,查看web.xml配置文件,找到Spring MVC相關(guān)配置。

<servlet><servlet-name>spring-mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-mvc.xml</param-value></init-param><load-on-startup>1</load-on-startup> </servlet>

配置很簡(jiǎn)單,只是配置了一個(gè)類型為DispatcherServlet類型的Servlet,并設(shè)置了初始化參數(shù)。那DispatcherServlet是什么呢?

2.2 DispatcherServlet類介紹

查看API文檔

從繼承圖看出最終繼承自HttpServlet,其實(shí)就是一個(gè)普通的Servlet。那為什么這個(gè)Servlet就能完成Spring MVC一系列復(fù)雜的功能呢?繼續(xù)往下看。

2.3 DispatcherServlet工作流程

DispatcherServlet工作流程如下:

(1) 所有請(qǐng)求先發(fā)到DispacherServlet 。

(2) DispacherServlet根據(jù)請(qǐng)求地址去查詢相應(yīng)的Controller,然后返回給DispacherServlet。

(3) DispacherServlet得到Controller后,讓Controler處理相應(yīng)的業(yè)務(wù)邏輯。

(4) Controler處理處理完后將結(jié)果返回給DispacherServlet。

(5) DispacherServlet把得到的結(jié)果用視圖解析器解析后獲得對(duì)應(yīng)的頁面。

(6) DispacherServlet跳轉(zhuǎn)到解析后的頁面。

在整個(gè)過程中DispatcherServlet承當(dāng)了一個(gè)中心控制器的角色來處理各種請(qǐng)求。

2.4 DispatcherServlet上下文繼承關(guān)系

上圖來自Spring官網(wǎng):

https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html

從圖中可以看到DispatcherServlet里面有一個(gè) Servlet WebApplicationContext,繼承自 Root WebApplicationContext。

從上篇文章中我們知道WebApplicationContext其實(shí)就是一個(gè)IOC容器,root WebApplicationContext是Spring容器。

這說明DispatcherServlet中里創(chuàng)建了一個(gè)IOC容器并且這個(gè)容器繼承了Spring 容器,也就是Spring的子容器。

而且官方文檔中還有如下一段文字描述:

For many applications, having a single WebApplicationContext is simple and suffices. It is also possible to have a context hierarchy where one root WebApplicationContext is shared across multiple DispatcherServlet (or other Servlet) instances, each with its own child WebApplicationContext configuration. See Additional Capabilities of the ApplicationContext for more on the context hierarchy feature.The root WebApplicationContext typically contains infrastructure beans, such as data repositories and business services that need to be shared across multiple Servlet instances. Those beans are effectively inherited and can be overridden (that is, re-declared) in the Servlet-specific child WebApplicationContext, which typically contains beans local to the given Servlet.

結(jié)合圖和上述文字我們可以得出以下信息:

  • 應(yīng)用中可以包含多個(gè)IOC容器。
  • DispatcherServlet的創(chuàng)建的子容器主要包含Controller、view resolvers等和web相關(guān)的一些bean。
  • 父容器root WebApplicationContex主要包含包含一些基礎(chǔ)的bean,比如一些需要在多個(gè)servlet共享的dao、service等bean。
  • 如果在子容器中找不到bean的時(shí)候可以去父容器查找bean。
  • 看到這里也許大家心中也許就明白文章開頭中我說的Spring MVC中的父子容器了,對(duì)那個(gè)問題也有了自己的判斷和答案。

    當(dāng)然文章還沒有結(jié)束,畢竟這還僅限于對(duì)官方文檔的理解,為了進(jìn)一步驗(yàn)證,我們拿出終極武器:

    閱讀源碼!

    2.5 DispatcherServlet源碼分析

    本小節(jié)我們分為Spring MVC容器的創(chuàng)建和bean的獲取兩部分進(jìn)行分析。

    2.5.1 Spring MVC容器的創(chuàng)建

    前面分析到DispatcherServlet本質(zhì)上還是一個(gè)Servlet ,既然是Servlet ,了解Servlet生命周期的同學(xué)都知道Web 容器裝載Servlet第一步是執(zhí)行init()函數(shù),因此以DispatcherServlet 的init函數(shù)為突破口進(jìn)行分析。

    @Override public final void init() throws ServletException {// 1.讀取init parameters 等參數(shù),其中就包括設(shè)置contextConfigLocation PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);//2.初始化servlet中使用的beaninitServletBean(); }

    在第1步讀取init parameter的函數(shù)最終會(huì)調(diào)用setContextConfigLocation()設(shè)置配置文件路徑。此處重點(diǎn)介紹initServletBean(),繼續(xù)跟蹤。

    Override protected final void initServletBean() throws ServletException {//初始化webApplicationContextthis.webApplicationContext = initWebApplicationContext(); } protected WebApplicationContext initWebApplicationContext() {//1.獲得rootWebApplicationContextWebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = null;//2.如果還沒有webApplicatioinContext,創(chuàng)建webApplicationContextif (wac == null) {//創(chuàng)建webApplicationContextwac = createWebApplicationContext(rootContext);}return wac; }

    可以看到上面初始化webApplicationContext分為2步。

    (1)獲取父容器rootWebApplicationContext。

    (2)創(chuàng)建子容器。

    我們先看看rootWebApplicationContext是如何獲取的。

    public static WebApplicationContext getWebApplicationContext(ServletContext sc) {return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); }public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {Object attr = sc.getAttribute(attrName);return (WebApplicationContext) attr; }

    從上面代碼中我沒看到是從ServletContext獲取了名為“WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE”的webApplicationContext。

    認(rèn)真看過上篇文章的同學(xué)應(yīng)該記得這個(gè)屬性是在Spring初始化 容器initWebApplicationContext()函數(shù)中的第3步設(shè)置進(jìn)去的,取得的值即Spring IOC容器。

    繼續(xù)看如何創(chuàng)建webApplicationContext。

    protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {return createWebApplicationContext((ApplicationContext) parent); } createWebApplicationContext(ApplicationContext parent) {//1.獲取WebApplicationContext實(shí)現(xiàn)類,此處其實(shí)就是XmlWebApplicationContextClass<?> contextClass = getContextClass();//生成XmlWebApplicationContext實(shí)例ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);//2.設(shè)置rootWebApplicationContext為父容器 wac.setParent(parent);//3.設(shè)置配置文件wac.setConfigLocation(getContextConfigLocation());//4.配置webApplicationContext.configureAndRefreshWebApplicationContext(wac);return wac; } protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {//開始處理beanwac.refresh(); }

    看到這里同學(xué)們有沒有是曾相識(shí)的感覺。是的,這段邏輯和上篇文章創(chuàng)建Spring IOC的邏輯類似。

    唯一不同的是在第2步會(huì)把Spring容器設(shè)置為自己的父容器。至于新建容器中bean的注冊(cè)、解析、實(shí)例化等流程和Spring IOC容器一樣都是交給XmlWebApplicationContext類處理,還沒有掌握的同學(xué)可以看上篇文章。

    2.5.2 Spring MVC Bean的獲取

    Spring MVC bean的獲取其實(shí)我們?cè)谏掀恼乱呀?jīng)介紹過,這次再單拎出來介紹一下,加深記憶。

    protected <T> T doGetBean(// 獲取父BeanFactoryBeanFactory parentBeanFactory = getParentBeanFactory();//如果父容器不為空,且本容器沒有注冊(cè)此bean就去父容器中獲取beanif (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// 如果父容器有該bean,則調(diào)用父beanFactory的方法獲得該beanreturn (T) parentBeanFactory.getBean(nameToLookup,args);}//如果子容器注冊(cè)了bean,執(zhí)行一系列實(shí)例化bean操作后返回bean.//此處省略實(shí)例化過程.....return (T) bean; }

    上面代碼就可以對(duì)應(yīng)官方文檔中“如果子容器中找不到bean,就去父容器找”的解釋了。

    3.小結(jié)

    看完上面的介紹,相信大家對(duì)Spring MVC父子容器的概念都有所了解,現(xiàn)在我們分析文章開頭的問題。

    如果spring.xml和spring-mvc.xml定義了相同id的bean會(huì)怎樣?假設(shè)id=test。

    1.首先Spring 初始化,Spring IOC 容器中生成一個(gè)id為test bean實(shí)例。

    2.Spring MVC開始初始化,生成一個(gè)id為test bean實(shí)例。

    此時(shí),兩個(gè)容器分別有一個(gè)相同id的bean。那用起來會(huì)不會(huì)混淆?

    答案是不會(huì)。

    當(dāng)你在Spring MVC業(yè)務(wù)邏輯中使用該bean時(shí),Spring MVC會(huì)直接返回自己容器的bean。

    當(dāng)你在Spring業(yè)務(wù)邏輯中使用該bean時(shí),因?yàn)樽尤萜鞯腷ean對(duì)父親是不可見的,因此會(huì)直接返回Spring容器中的bean。

    雖然上面的寫法不會(huì)造成問題。但是在實(shí)際使用過程中,建議大家都把bean定義都寫在spring.xml文件中。

    因?yàn)槭褂脝卫齜ean的初衷是在IOC容器中只存在一個(gè)實(shí)例,如果兩個(gè)配置文件都定義,會(huì)產(chǎn)生兩個(gè)相同的實(shí)例,造成資源的浪費(fèi),也容易在某些場(chǎng)景下引發(fā)缺陷。

    4.尾聲

    現(xiàn)在大家基本都不使用在xml文件中定義bean的形式,而是用注解來定義bean,然后在xml文件中定義掃描包。如下:

    <context:component-scan base-package="xx.xx.xx"/>

    那如果在spring.xml和spring-mvc.xml配置了重復(fù)的包會(huì)怎樣呢?

    如果本文看明白的同學(xué)此時(shí)已經(jīng)知道了答案。

    答案是會(huì)在兩個(gè)父子IOC容器中生成大量的相同bean,這就會(huì)造成內(nèi)存資源的浪費(fèi)。

    也許有同學(xué)想到,那只在spring.xml中設(shè)置掃描包不就能避免這種問題發(fā)生了嗎,答案是這樣嗎?

    大家可以試試,這樣會(huì)有什么問題。如果不行,那是為什么呢?

    欲知分曉,敬請(qǐng)期待下篇分解!

    如果想獲得更多,歡迎關(guān)注公眾號(hào):七分熟pizza

    公眾號(hào)里我會(huì)分享更多技術(shù)以及職場(chǎng)方面的經(jīng)驗(yàn),大家有什么問題也可以直接在公眾號(hào)向我提問交流。

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的boot spring 没有父子容器_Spring 系列(二):Spring MVC的父子容器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲激情在线观看 | 成人六区| 久久九九99| 一级a毛片免费观看久久精品 | 天天综合一区 | 天堂av在线中文 | 尤物国产在线 | 久久黄色影视 | 91在线观看喷潮 | 亚洲福利 | 国产亚洲精品久久久久婷婷瑜伽 | 亚洲一区,二区 | 亚洲一区二区欧美 | 天天av天天爽 | 免费人成网站 | 99精品国产一区二区 | 国产情侣久久 | 色91视频 | 蜜桃av成人永久免费 | 视频在线亚洲 | a级一片| 国产精品午夜一区二区 | 中文字幕一区二区三区人妻不卡 | 成人a视频在线观看 | 亚洲精品国产精品国自产观看浪潮 | 最新av在线网址 | 国产无码久久精品 | 成人动漫亚洲 | 欧美视频网址 | 99爱精品| 国产美女在线免费观看 | 免费一区二区三区视频在线 | 日韩精品一二三 | 国产精品高潮视频 | 一级淫片a | 日韩精品一区二区三区四区五区 | 小萝莉末成年一区二区 | 高跟肉丝丝袜呻吟啪啪网站av | 亚洲成熟少妇 | 日本天天色| 亚洲精品高清在线观看 | 亚洲精品久久久久久无码色欲四季 | 欧美精品一区二区三区四区五区 | 国产色拍 | 欧美一卡二卡在线观看 | av中文字幕网 | 国产在线视频你懂的 | 久久国产一区二区 | 快色污 | 91av国产精品 | 一级高清毛片 | 极品少妇xxxx| av在线播放国产 | 嫦娥性艳史bd | 无码国产69精品久久久久同性 | 我爱52av| 国产又粗又大又硬 | 91在线视频在线观看 | 国产后入又长又硬 | 久久9久久 | 欧美性猛交xxx乱大交3 | 人妻射精一区二区 | 好吊妞精品| 林雅儿欧洲留学恋爱日记在线 | 熟妇人妻无乱码中文字幕真矢织江 | 国产男人搡女人免费视频 | 午夜亚洲av永久无码精品 | 欧美综合专区 | 国产精品久久久久久免费观看 | 无码av天堂一区二区三区 | 国产精品美女www爽爽爽 | 亚洲a∨无码无在线观看 | 亚洲精品一区二区三 | 国产97在线观看 | 两个女人互添下身爱爱 | 99色精品 | 性欧美高清 | 午夜亚洲AV永久无码精品蜜芽 | 免费看一级片 | 在线观看免费观看 | 黑人玩弄人妻一区二区三区 | 免费在线中文字幕 | 超碰青草 | 69精品无码成人久久久久久 | 丁香花电影免费播放电影 | 豆豆色成人网 | 国产欧美日韩中文字幕 | 精品久久无码视频 | 久久精精品久久久久噜噜 | 国产91看片 | 成年人看的羞羞网站 | 久久精品这里只有精品 | 欧美一区2区三区4区公司 | 国产真人无遮挡作爱免费视频 | 福利片第一页 | 中文字幕在线一区 | 日韩大片免费看 | 亚洲精品电影在线观看 | 成人激情片 |