1. 程式人生 > >Spring Framework啟動詳解

Spring Framework啟動詳解

service 控制 ice trap pri pos warn 層次結構 initial

之前一直對Spring啟動的過程很迷糊,所以這次國慶梳理一下。

Spring啟動一言以蔽之:創建一個根應用上下文。(因為其他的所有的應用上下文都可以通過各種方式繼承它)

(一)了解應用上下文

Spring Framework容器以一個或多個應用上下文的形式存在,由org.springframework.context.ApplicationContext接口表示。每一個應用上下文管理著一組bean、執行業務邏輯的Java對象、執行任務、持久化和獲取持久化數據、響應HTTP請求等。由Spring管理的bean可以自動進行依賴註入、消息通知、定時方法執行、bean驗證和執行其他關鍵的Spring服務。

在多個應用上下文組成的層次結構中,任何由Spring管理的bean都可以訪問相同的應用上下文、父親應用上下文、父親的父親應用上下文的bean(依次類推)。但是它們不能訪問兄弟或孩子應用上下文的bean。這對於定於一組共享應用模塊來說非常有用,它可以將應用模塊彼此隔開。

技術分享圖片

有許多接口都繼承了ApplicationContext,也有許多類實現了它:

a)ConfigurableApplicationContext接口是可配置的,而基本的ApplicationContext是只讀的;

b)org.springframework.web.context.WebApplicationContext和ConfiguableWebApplicationContext接口被設計用於Servlet容器中運行的Java EE Web應用程序,它們提供了對底層ServletContext和ServletConfig的訪問;

c)具體類ClassPathXmlApplicationContext和FileSystemXmlApplicationContext被設計用於在獨立運行的應用程序中從XML文件加載Spring配置,而XmlWebApplicationContext被設計用於在Java EE Web應用程序中實現相同的目標;

d)如果需要使用Java而不是使用XML以編程的方式對Spring進行配置,那麽AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext類分別可用於獨立運行的應用程序和Java EE Web應用程序中。

(二)啟動Spring Framework

配置和啟動Spring Framework是兩個不同的任務,並且相互獨立,都可以通過多種不同的方式實現。當配置告訴Spring如何運行它所包含的應用程序時,啟動進程將啟動Spring並將配置指令傳遞給它。

在Java SE應用程序中,只有一種方式啟動Spring:通過應用程序中的public static void main(String ...)方法以編程的方式啟動;

在Java EE應用程序中,有兩種選擇:可以使用XML創建部署描述符啟動Spring,也可以在javax.servlet.ServletContainerInitializer中通過編程的方式啟動Spring。

a)使用部署描述符啟動Spring

<context-param>                <!--Spring上下文配置-->
   <param-name>contextConfigLocation</param-name>              
   <param-value>/WEB-INF/rootContext.xml</param-value>        <!--指定配置文件地址及文件名稱-->
</context-param>
<listener>         <!--上下文初始化監聽器-->
   <listener-class>org.springframework.web.context.ContextloadListener</listener-class>
</listener>

<servlet>        <!--配置Servlet-->
    <servlet-name>springDispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/servletContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springDispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

ContextLoaderListerner將在Web應用程序啟動時被初始化(因為它實現了ServletContextListerner,所有它將在所有的Servlet之前初始化),然後從contextConfigLocation上下文初始化參數指定的/WEB-INF/rootContext.xml文件中加載根應用上下文,並啟動根應用上下文。

其中出現了兩個contextConfigLocation,兩者並不沖突,前者作用於整個Servlet上下文,而後者只作用於它所指定的Servlet。

b)在初始化器中使用編程的方式啟動Spring

public class Bootstrap implements WebApplicationInitializer{
    @overvide
    public void onStartup(ServletContext container){
        XmlWebApplicationContex rootContext = new XmlWebApplicationContex();
        rootContext.setConfigLocation("/WEB-INF/rootContext.xml");
        container.addListener(new ContextLoaderListerner(rootContext));

        XmlWebApplicationContex servletContext = new XmlWebApplicationContex();
        servletCOntext.setConfigLocation("/WEB-INF/servletContext.xml");
        ServletRegistration.Dynamic dispatcher = container.addServlet(
            "springDispatcher", new DispatcherServlet(servletContext)
            );
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");

    }
}

這個啟動類等同於之前使用的部署描述符,方便理解;當然也還存在使用純Java的方式啟動和配置Spring。

(三)配置Spring Framework與註釋

Spring的配置一般可以完全在XML文件的<beans>空間中配置完成,但是在龐大的企業應用程序中,可能會定義數百個bean,顯然這種方式是很難基於Spring源碼去調試的,所以基於這個考慮出現了混合配置的概念。

混合配置的核心是組件掃描和註解配置。通過使用組件掃描,Spring將掃描通過特定註解指定的包查找類,標註了@Component(@org.springframework.stereotype.Component)、@Controller、@Repository、@Service的類將成為Spring管理的bean,其中也可以創建自己的組件註釋;註解配置的一個關鍵註解是:@org.springframework.beans.factoryannotation.Autowired,@Autowired聲明了Spring應該在實例化之後註入的依賴。

Warnning:組件掃描默認將掃描所有的@Component註解,要想做到分離bean,使得根應用上下文保存服務、倉庫和其他業務邏輯片段,而DispatcherServlet的應用上下文只包含Web控制器,可以通過filter增加黑白名單來實現

applicationContext.mxl中:
 <context:component-scan base-package="com.wrox">
      <context:exclude-filter expression="org.springframework.stereotype.Controller"    type="annotation" /> 
 </context:component-scan>
 
spring-mvc.xml中:
  <context:component-scan base-package="com.wrox"   use-default-filters="false"> 
      <context:include-filter expression="org.springframework.stereotype.Controller"    type="annotation" /> 
 </context:component-scan>

參考目錄:

1. 《Java Web高級編程》 王肖峰版 清華大學出版社——第十二章

2. Spring Framework的API文檔:https://docs.spring.io/spring/docs/4.0.x/javadoc-api/

Spring Framework啟動詳解