亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                阿里跳槽來的,連Spring容器與SpringMVC的容器的區(qū)別都不知道

                說起spring容器和SpringMVC容器,很多剛接觸spring框架的同志都有點懵,甚至是一頭霧水,分不清楚兩者的關系和區(qū)別。這倆容器呢雖然有必然的聯系,但是他們的區(qū)別也是有的。下面我就簡單描述下。

                一、前言

                首先在我們開發(fā)中會與到各種各樣的容器,今天我們就說一下spring 容器與springmvc容器。Spring和SpringMVC作為Bean管理容器和MVC層的默認框架,已被眾多web應用采用。但是在實際應用中,初級開發(fā)者常常會因對Spring和SpringMVC的配置失當導致一些奇怪的異?,F象,比如Controller的方法無法攔截、Bean被多次加載等問題,這種情況發(fā)生的根本原因在于開發(fā)者對Spring容器和SpringMVC容器之間的關系了解不夠深入。

                在Spring整體框架的核心概念中,容器的核心思想是管理Bean的整個生命周期。但在一個項目中,Spring容器往往不止一個,最常見的場景就是在一個項目中引入Spring和SpringMVC這兩個框架,其本質就是兩個容器。首先 springmvc和spring它倆都是容器,容器就是管理對象的地方,例如Tomcat,就是管理servlet對象的,而springMVC容器和spring容器,就是管理bean對象的地方,再說的直白點,springmvc就是管理controller對象的容器,spring就是管理service和dao的容器,這下你明白了吧。所以我們在springmvc的配置文件里配置的掃描路徑就是controller的路徑,而spring的配置文件里自然配的就是service和dao的路徑

                SpringMVC.xml文件所配置的路徑:

                applicationContext-service.xml文件所配置的路徑:

                其次, spring容器和springmvc容器的關系是父子容器的關系。spring容器是父容器,springmvc是子容器。在子容器里可以訪問父容器里的對象,但是在父容器里不可以訪問子容器的對象,說的通俗點就是,在controller里可以訪問service對象,但是在service里不可以訪問controller對象  所以這么看的話,所有的bean,都是被spring或者springmvc容器管理的,他們可以直接注入。然后springMVC的攔截器也是springmvc容器管理的,所以在springmvc的攔截器里,可以直接注入bean對象。

                二、Spring容器、SpringMVC容器與ServletContext之間的關系

                在Web容器中配置Spring時,你可能已經司空見慣于web.xml文件中的以下配置代碼,下面我們以該代碼片段為基礎來了解Spring容器、SpringMVC容器與ServletContext之間的關系。要想理解這三者的關系,需要先熟悉Spring是怎樣在web容器中啟動起來的。Spring的啟動過程其實就是其Spring IOC容器的啟動過程。特別地,對于web程序而言,IOC容器啟動過程即是建立上下文的過程。

                …org.springframework.web.context.ContextLoaderListenercontextConfigLocationclasspath:applicationContext.xmlSpringMVCorg.springframework.web.servlet.DispatcherServletcontextConfigLocationclasspath:springmvc.xml1SpringMVC/ …

                Spring的啟動過程

              1. 對于一個web應用,其部署在web容器中,web容器提供其一個全局的上下文環(huán)境,這個上下文就是ServletContext,其為后面的spring IoC容器提供宿主環(huán)境;
              2. 在web.xml中會提供有contextLoaderListener。在web容器啟動時,會觸發(fā)容器初始化事件,此時contextLoaderListener會監(jiān)聽到這個事件,其contextInitialized方法會被調用。在這個方法中,spring會初始化一個啟動上下文,這個上下文被稱為根上下文,即WebApplicationContext。WebApplicationContext是一個接口類,確切的說,其實際的實現類是XmlWebApplicationContext,它就是spring的IoC容器,其對應的Bean定義的配置由web.xml中的標簽指定。在這個IoC容器初始化完畢后,Spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE為屬性Key,將其存儲到ServletContext中,便于獲??;
              3. ContextLoaderListener監(jiān)聽器初始化完畢后,開始初始化web.xml中配置的Servlet,這個servlet可以配置多個,以最常見的DispatcherServlet為例,這個servlet實際上是一個標準的前端控制器,用以轉發(fā)、匹配、處理每個servlet請求。DispatcherServlet上下文在初始化的時候會建立自己的IoC上下文,用以持有spring mvc相關的bean。特別地,在建立DispatcherServlet自己的IoC上下文前,會利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先從ServletContext中獲取之前的根上下文(即WebApplicationContext)作為自己上下文的parent上下文。有了這個parent上下文之后,再初始化自己持有的上下文。這個DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化處理器映射、視圖解析等。這個servlet自己持有的上下文默認實現類也是mlWebApplicationContext。初始化完畢后,spring以與servlet的名字相關(此處不是簡單的以servlet名為Key,而是通過一些轉換,具體可自行查看源碼)的屬性為屬性Key,也將其存到ServletContext中,以便后續(xù)使用。這樣每個servlet就持有自己的上下文,即擁有自己獨立的bean空間,同時各個servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定義的那些bean。
              4. Spring容器與SpringMVC的容器聯系與區(qū)別

                ContextLoaderListener中創(chuàng)建Spring容器主要用于整個Web應用程序需要共享的一些組件,比如DAO、數據庫的ConnectionFactory等;而由DispatcherServlet創(chuàng)建的SpringMVC的容器主要用于和該Servlet相關的一些組件,比如Controller、ViewResovler等。它們之間的關系如下:

                作用范圍

                子容器(SpringMVC容器)可以訪問父容器(Spring容器)的Bean,父容器(Spring容器)不能訪問子容器(SpringMVC容器)的Bean。也就是說,當在SpringMVC容器中getBean時,如果在自己的容器中找不到對應的bean,則會去父容器中去找,這也解釋了為什么由SpringMVC容器創(chuàng)建的Controller可以獲取到Spring容器創(chuàng)建的Service組件的原因。

                具體實現

                在Spring的具體實現上,子容器和父容器都是通過ServletContext的setAttribute方法放到ServletContext中的。但是,ContextLoaderListener會先于DispatcherServlet創(chuàng)建ApplicationContext,DispatcherServlet在創(chuàng)建ApplicationContext時會先找到由ContextLoaderListener所創(chuàng)建的ApplicationContext,再將后者的ApplicationContext作為參數傳給DispatcherServlet的ApplicationContext的setParent()方法。也就是說,子容器的創(chuàng)建依賴于父容器的創(chuàng)建,父容器先于子容器創(chuàng)建。在Spring源代碼中,你可以在FrameServlet.java中找到如下代碼:

                wac.setParent(parent);

                其中,wac即為由DisptcherServlet創(chuàng)建的ApplicationContext,而parent則為有ContextLoaderListener創(chuàng)建的ApplicationContext。此后,框架又會調用ServletContext的setAttribute()方法將wac加入到ServletContext中。

                三、Spring容器和SpringMVC容器的配置

                在Spring整體框架的核心概念中,容器是核心思想,就是用來管理Bean的整個生命周期的,而在一個項目中,容器不一定只有一個,Spring中可以包括多個容器,而且容器間有上下層關系,目前最常見的一種場景就是在一個項目中引入Spring和SpringMVC這兩個框架,其實就是兩個容器:Spring是根容器,SpringMVC是其子容器。在上文中,我們提到,SpringMVC容器可以訪問Spring容器中的Bean,Spring容器不能訪問SpringMVC容器的Bean。但是,若開發(fā)者對Spring容器和SpringMVC容器之間的關系了解不夠深入,常常會因配置失當而導致同時配置Spring和SpringMVC時出現一些奇怪的異常,比如Controller的方法無法攔截、Bean被多次加載等問題。

                在實際工程中,一個項目中會包括很多配置,根據不同的業(yè)務模塊來劃分,我們一般思路是各負其責,明確邊界,即:Spring根容器負責所有其他非controller的Bean的注冊,而SpringMVC只負責controller相關的Bean的注冊,下面我們演示這種配置方案。

                (1). Spring容器配置

                Spring根容器負責所有其他非controller的Bean的注冊:

                (2). SpringMVC容器配置

                SpringMVC只負責controller相關的Bean的注冊,其中@ControllerAdvice用于對控制器進行增強,常用于實現全局的異常處理類:

                在中可以添加use-default-filters,Spring配置中的use-default-filters用來指示是否自動掃描帶有@Component、@Repository、@Service和@Controller的類。默認為true,即默認掃描。如果想要過濾其中這四個注解中的一個,比如@Repository,可以添加子標簽,如下:

                而子標簽是用來添加掃描注解的:

                四、Spring容器和SpringMVC容器的配置失當帶來的問題

                問題描述

                在一個項目中,想使用Spring AOP在Controller中切入一些邏輯,但發(fā)現不能切入到Controller的中,但可以切入到Service中。最初的配置情形如下:

                1). Spring的配置文件application.xml包含了開啟AOP自動代理、Service掃描配置以及Aspect的自動掃描配置,如下所示:

                2). Spring MVC的配置文件spring-mvc.xml主要內容是Controller層的自動掃描配置。

                3). 增強代碼為如下:

                @Component@Aspectpublic class SecurityAspect {private static final String DEFAULT_TOKEN_NAME = “X-Token”;private TokenManager tokenManager;@Resource(name = “tokenManager”)public void setTokenManager(TokenManager tokenManager) {this.tokenManager = tokenManager;}@Around(“@annotation(org.springframework.web.bind.annotation.RequestMapping)”)public Object execute(ProceedingJoinPoint pjp) throws Throwable {// 從切點上獲取目標方法MethodSignature methodSignature = (MethodSignature) pjp.getSignature();Method method = methodSignature.getMethod();// 若目標方法忽略了安全性檢查,則直接調用目標方法if (method.isAnnotationPresent(IgnoreSecurity.class)) {System.out.println(“method.isAnnotationPresent(IgnoreSecurity.class) : “+ method.isAnnotationPresent(IgnoreSecurity.class));return pjp.proceed();}// 從 request header 中獲取當前 tokenString token = WebContext.getRequest().getHeader(DEFAULT_TOKEN_NAME);// 檢查 token 有效性if (!tokenManager.checkToken(token)) {String message = String.format(“token [%s] is invalid”, token);throw new TokenException(message);}// 調用目標方法return pjp.proceed();}}

                4). 需要被代理的Controller如下:

                @RestController@RequestMapping(“/tokens”)public class TokenController {private UserService userService;private TokenManager tokenManager;public UserService getUserService() {return userService;}@Resource(name = “userService”)public void setUserService(UserService userService) {this.userService = userService;}public TokenManager getTokenManager() {return tokenManager;}@Resource(name = “tokenManager”)public void setTokenManager(TokenManager tokenManager) {this.tokenManager = tokenManager;}@RequestMapping(method = RequestMethod.POST)@IgnoreSecuritypublic Response login(@RequestParam(“uname”) String uname,@RequestParam(“passwd”) String passwd) {boolean flag = userService.login(uname, passwd);if (flag) {String token = tokenManager.createToken(uname);System.out.println(“**** Token **** : ” + token);return new Response().success(“Login Success…”);}return new Response().failure(“Login Failure…”);}@RequestMapping(method = RequestMethod.DELETE)@IgnoreSecuritypublic Response logout(@RequestParam(“uname”) String uname) {tokenManager.deleteToken(uname);return new Response().success(“Logout Success…”);}}

                在運行過程中,發(fā)現這樣配置并沒有起作用,AOP配置不生效,沒有生成TokenController的代理。

                解決方案

                由上一節(jié)可知,原因有兩點:

                • Spring容器與SpringMVC容器分別基于各自的配置文件進行初始化,所以,在SpringMVC容器創(chuàng)建TokenController時,由于其沒有啟用AOP代理,導致SpringMVC容器沒有為TokenController生成代理,所以沒有生效。
                • 雖然父容器啟用了AOP代理,但由于父子容器的獨立性,無濟于事。

                因此,我們只需要在SpringMVC的配置文件中添加Aspect的自動掃描配置即可實現所要的效果。此外,一般地,SpringMVC容器只管理Controller,剩下的Service、Repository 和 Component 由Spring容器只管理,不建議兩個容器上在管理Bean上發(fā)生交叉。因此,建議配置為:

                SpringMVC 配置:

                Spring配置:

                總結

                springmvc容器是spring容器的子容器,但是子容器可以父容器的bean, 但是父容器不能訪問子容器的bean。Spring容器和SpringMVC容器雖然是父容器與子容器的關系,但二者之間具有一定的獨立性。具體來說,兩個容器基于各自的配置文件分別進行初始化,只有在子容器找不到對應的Bean時,才回去父容器中去找并加載

                寫在最后

                希望通過這篇文章能讓大家分清楚spring容器和SpringMVC容器的關系與區(qū)別。雖然這些知識點都是老生常談,不否認還是很多人分不清和不了解,但知識點不管是不是老生常談也都是需要掌握的,畢竟基礎要打好,這樣才能有更高的成就賺到更多的錢呀。好了本文到此結束了,希望能對鐵子們有幫助和收獲。喜歡的鐵子們可以點點贊和關注, 文章持續(xù)更新,也可以評論出你想看哪一塊技術。鐵子們的支持是我的動力,創(chuàng)作離不開鐵子們的支持,在此先感謝大家!

                鄭重聲明:本文內容及圖片均整理自互聯網,不代表本站立場,版權歸原作者所有,如有侵權請聯系管理員(admin#wlmqw.com)刪除。
                用戶投稿
                上一篇 2022年9月17日 07:07
                下一篇 2022年9月17日 07:07

                相關推薦

                • 暗區(qū)突圍倉庫怎么擴容 倉庫擴容方法介紹

                  暗區(qū)突圍倉庫的容量是有限的,玩家在儲藏物品的時候發(fā)現倉庫不夠用,那么大家可以選擇給倉庫擴容,今天小編就來給大家分享一下倉庫擴容的方法,詳細可以多參考下面的攻略,了解倉庫擴容的更多技…

                  2022年11月17日
                • 蘋果exe文件怎么打開電腦,mac打開exe文件方法教程

                  使用了Mac系統(tǒng)之后,總會惦記著Windows系統(tǒng)的軟件,無奈兩個系統(tǒng)的程序文件不一樣,所以也互不相通。為了讓MacBook能夠使用上Windows的應用程序,許多人都會給電腦安裝…

                  2022年10月29日
                • 介紹創(chuàng)建博客的5個步驟(創(chuàng)建博客的步驟有哪些)

                  個人博客要考慮的一大因素便是成本。 國內比較大的服務器提供商,如阿里云,騰訊云等最低配置的服務器,一個月的消費在100元左右,這對于一個剛剛建立博客的人來說,顯然是不劃算的。在今天…

                  2022年10月22日
                • 如何優(yōu)雅的關閉 Java線程池

                  簡介 在開發(fā)中使用線程池去執(zhí)行異步任務是比較普遍的操作,然而雖然有些異步操作我們并不十分要求可靠性和實時性,但總歸業(yè)務還是需要的。如果在每次的服務發(fā)版過程中,我們不去介入線程池的?!?/p>

                  2022年8月30日
                • 華為云重磅發(fā)布《金融云原生2.0發(fā)展應用白皮書》

                  8月18日, 2022金融洞察力峰會在北京成功舉行,華為云受邀發(fā)表了《云原生,釋放金融新生產力》的主題演講,并發(fā)布了《金融云原生2.0發(fā)展應用白皮書》。華為云在會上表示,數字化轉型…

                  2022年8月20日
                • Linux下常用的Shell腳本

                  Dos 攻擊防范(自動屏蔽攻擊 IP) #!/bin/bashDATE=$(date +%d/%b/%Y:%H:%M)LOG_FILE=/usr/local/nginx/logs/…

                  2022年8月20日
                • 2.容器《小王子》解讀版

                  Chapter02容器 兩個主人公相遇,作為大人的我,飛機失事,落到了沙漠,遇到了外星球來的小王子,由此展開的一系列我對小王子的了解。 小王子出現在作者身邊,堅持讓我給他畫一只綿羊…

                  2022年8月19日
                • 二維材料中首次實現核自旋量子位控制

                  研究人員使用光和電子自旋量子位來控制二維材料中的核自旋。 圖片來源:Second Bay工作室/美國科學促進會網站 據15日發(fā)表在《自然·材料》上的論文,美國普渡大學的研究人員通過…

                  2022年8月18日
                • 手性骨架單晶微管的同步組裝

                  手性骨架單晶微管的同步組裝 文章出處:Osamu Oki, Hiroshi Yamagishi, Yasuhiro Morisaki, Ryo Inoue, Kana Ogawa,…

                  2022年8月17日
                • 返回地球的龍宮小行星樣本揭示了太陽系的組成部分

                  龍宮小行星 就在12個多月前(2020年12月6日),我們在澳大利亞內陸的伍默拉(Woomera),等待天空中的一道亮光,以見證隼鳥2號”宇宙飛船從航行中返回,回收一顆名為龍宮的近…

                  2022年8月16日

                聯系我們

                聯系郵箱:admin#wlmqw.com
                工作時間:周一至周五,10:30-18:30,節(jié)假日休息