Spring和SpringMVC的關系


說到spring和springmvc,其實有很多工作好多年的人也分不清他們有什么區別,如果你問他項目里用的什么MVC技術,他會說我們用的spring和mybatis,或者spring和hibernate。

在潛意識里會認為springmvc就是spring,之前我也是這么認為的,哈哈。 

  雖然springMVC和spring有必然的聯系,但是他們的區別也是有的。下面我就簡單描述下

  首先 springmvc和spring它倆都是容器,容器就是管理對象的地方,例如Tomcat,就是管理servlet對象的,而springMVC容器和spring容器,就是管理bean對象的地方,再說的直白點,springmvc就是管理controller對象的容器,spring就是管理service和dao的容器,這下你明白了吧。所以我們在springmvc的配置文件里配置的掃描路徑就是controller的路徑,而spring的配置文件里自然配的就是service和dao的路徑

  spring-mvc.xml

<context:component-scan base-package="com.smart.controller" />
  applicationContext-service.xml

<!-- 掃描包加載Service實現類 -->
    <context:component-scan base-package="com.smart.service"></context:component-scan>
或者
<context:component-scan base-package="com.smart">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
 

  至於他是怎么管理起來的,又是怎么注入屬性的,這就涉及到他們底層的實現技術了
  其次, spring容器和springmvc容器的關系是父子容器的關系。spring容器是父容器,springmvc是子容器。在子容器里可以訪問父容器里的對象,但是在父容器里不可以訪問子容器的對象,說的通俗點就是,在controller里可以訪問service對象,但是在service里不可以訪問controller對象

  所以這么看的話,所有的bean,都是被spring或者springmvc容器管理的,他們可以直接注入。然后springMVC的攔截器也是springmvc容器管理的,所以在springmvc的攔截器里,可以直接注入bean對象。

<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/employee/**" ></mvc:mapping>
            <bean class="com.smart.core.shiro.LoginInterceptor" ></bean>
        </mvc:interceptor>
    </mvc:interceptors>
 


  而web容器又是什么鬼,
  web容器是管理servlet,以及監聽器(Listener)和過濾器(Filter)的。這些都是在web容器的掌控范圍里。但他們不在spring和springmvc的掌控范圍里。因此,我們無法在這些類中直接使用Spring注解的方式來注入我們需要的對象,是無效的,
web容器是無法識別的。

  但我們有時候又確實會有這樣的需求,比如在容器啟動的時候,做一些驗證或者初始化操作,這時可能會在監聽器里用到bean對象;又或者需要定義一個過濾器做一些攔截操作,也可能會用到bean對象。
那么在這些地方怎么獲取spring的bean對象呢?下面我提供兩個方法:

1、

public void contextInitialized(ServletContextEvent sce) {
  ApplicationContext context = (ApplicationContext) sce.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); 
  UserService userService = (UserService) context.getBean("userService");
}
 

2、

public void contextInitialized(ServletContextEvent sce) {
  WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()); 
  UserService userService = (UserService) webApplicationContext.getBean("userService"); 
}
  注意:以上代碼有一個前提,那就是servlet容器在實例化ConfigListener並調用其方法之前,要確保spring容器已經初始化完畢!而spring容器的初始化也是由Listener(ContextLoaderListener)完成,因此只需在web.xml中先配置初始化spring容器的Listener,然后在配置自己的Listener。

 

一圖勝千言

å¨è¿éæå¥å¾çæè¿°

 

web容器中有servlet容器,spring項目部署后存在spring容器和springmvc容器。其中spring控制service層和dao層的bean對象。springmvc容器控制controller層bean對象。servlet容器控制servlet對象。項目啟動是,首先 servlet初始化,初始化過程中通過web.xml中spring的配置加載spring配置,初始化spring容器和springmvc容器。待容器加載完成。servlet初始化完成,則完成啟動。
HTTP請求到達web容器后,會到達Servlet容器,容器通過分發器分發到具體的spring的Controller層。執行業務操作后返回結果。

 

總結:

Tomcat在啟動時給每個Web應用創建一個全局的上下文環境,這個上下文就是ServletContext,其為后面的Spring容器提供宿主環境。

Tomcat在啟動過程中觸發容器初始化事件,Spring的ContextLoaderListener會監聽到這個事件,它的contextInitialized方法會被調用,在這個方法中,Spring會初始化全局的Spring根容器,這個就是Spring的IoC容器,IoC容器初始化完畢后,Spring將其存儲到ServletContext中,便於以后來獲取。

Tomcat在啟動過程中還會掃描Servlet,一個Web應用中的Servlet可以有多個,以SpringMVC中的DispatcherServlet為例,這個Servlet實際上是一個標准的前端控制器,用以轉發、匹配、處理每個Servlet請求。

Servlet一般會延遲加載,當第一個請求達到時,Tomcat&Jetty發現DispatcherServlet還沒有被實例化,就調用DispatcherServlet的init方法,DispatcherServlet在初始化的時候會建立自己的容器,叫做SpringMVC 容器,用來持有Spring MVC相關的Bean。同時,Spring MVC還會通過ServletContext拿到Spring根容器,並將Spring根容器設為SpringMVC容器的父容器,請注意,Spring MVC容器可以訪問父容器中的Bean,但是父容器不能訪問子容器的Bean, 也就是說Spring根容器不能訪問SpringMVC容器里的Bean。說的通俗點就是,在Controller里可以訪問Service對象,但是在Service里不可以訪問Controller對象。

轉載:https://blog.csdn.net/a745233700/article/details/79172859


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM