多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > spring源碼研究之IoC容器在web容器中初始化過程

spring源碼研究之IoC容器在web容器中初始化過程

來源:程序員人生   發布時間:2015-04-01 08:41:10 閱讀次數:2887次

前段時間在公司做了1個項目,項目用了spring框架實現,WEB容器是Tomct 5,雖然說把項目做完了,但是1直對spring的IoC容器在web容器如何啟動和起作用的其實不清楚。所以就抽時間看1下spring的源代碼,借此了解它的原理。

    我們知道,對使用Spring的web利用,不必手動創建Spring容器,而是通過配置文件,聲明式的創建Spring容器。因此在Web利用中創建Spring容器有以下兩種方式:

    1. 直接在web.xml文件中配置創建Spring容器。

    2. 利用第3方MVC框架的擴大點,創建Spring容器。

    其實第1種方式是更加常見。為了讓Spring容器隨Web利用的啟動而啟動,有以下兩種方式:

    1. 利用ServletContextListener實現。

    2. 利用load-on-startup Servlet實現。

    Spring提供ServletContextListener的1個實現類ContextLoaderListener,該類可以作為Listener 使用,它會在創建時自動查找WEB-INF下的applicationContext.xml文件,因此,如果只有1個配置文件,并且文件名為applicationContext.xml,則只需在web.xml文件中增加以下配置片斷就能夠了

<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
如果有多個配置文件需要載入,則斟酌使用<context-param...>元夙來肯定配置文件的文件名。ContextLoaderListener加載時,會查找名為contentConfigLocation的初始化參數。因此,配置<context-param...>時就指定參數名為contextConfigLocation。

    帶多個配置文件的web.xml文件以下:

<context-param> <param-name>contextLoaderListener</param-name> <param-value> WEB-INF/*.xml, classpath:spring/*.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
  多個配置文件之間用“,”隔開。

 

    下面我們來看它的具體實現進程是怎樣的,首先我們從ContextLoaderListener入手,它的代碼以下:

public class ContextLoaderListener implements ServletContextListener { private ContextLoader contextLoader; /** * 這個方法就是用來初始化web application context的 */ public void contextInitialized(ServletContextEvent event) { this.contextLoader = createContextLoader(); this.contextLoader.initWebApplicationContext(event.getServletContext()); } /** * 創建1個contextLoader. * @return the new ContextLoader */ protected ContextLoader createContextLoader() { return new ContextLoader(); } ................ }
我們看到初始化web application context的時候,首先通過new ContextLoader()創建1個contextLoader,

   new ContextLoader()具體做了甚么事呢?ContextLoader的代碼片斷:

static { try { // 這里創建1個ClassPathResource對象,載入ContextLoader.properties,用于創建對應的ApplicationContext容器 // 這個文件跟ContextLoader類在同1個目錄下,文件內容如: // org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext // 如此說來,spring默許初始化的是XmlWebApplicationContext ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class); // 得到1個Properties對象,后面根據類名來創建ApplicationContext容器 defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); }catch (IOException ex) { throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage()); } }
代碼注釋里面已說得很清楚了,很容易理解吧?嘿嘿......

    再下來我們再看1下initWebApplicationContext方法的實現進程:

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) throws IllegalStateException, BeansException { // 從servletContext中獲得ApplicationContext容器;如果已存在,則提示初始化容器失敗,檢查web.xml文件中是不是定義有多個容器加載器 // ServletContext接口的簡述:public interface ServletContext // 定義了1系列方法用于與相應的servlet容器通訊,比如:取得文件的MIME類型,分派要求,或是向日志文件寫日志等。 // 每個web-app只能有1個ServletContext,web-app可以是1個放置有web application 文件的文件夾,也能夠是1個.war的文件。 // ServletContext對象包括在ServletConfig對象當中,ServletConfig對象在servlet初始化時提供servlet對象。 if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException( "Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ContextLoader* definitions in your web.xml!"); } servletContext.log("Initializing Spring root WebApplicationContext"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { // Determine parent for root web application context, if any. // 獲得父容器 ApplicationContext parent = loadParentContext(servletContext); // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. // 創建ApplicationContext容器 this.context = createWebApplicationContext(servletContext, parent); // 把容器放入到servletContext中 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); } return this.context; } catch (RuntimeException ex) { logger.error("Context initialization failed", ex); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; } catch (Error err) { logger.error("Context initialization failed", err); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err); throw err; } } 從上面的代碼可以看出,我們創建好的applicationContext容器會放在servletContext中。servletContext是甚么 呢? 在web容器中,通過ServletContext為Spring的IOC容器提供宿主環境,對應的建立起1個IOC容器的體系。其中,首先需要建立的是根上下文,這個上下文持有的對象可以有業務對象,數據存取對象,資源,事物管理器等各種中間層對象。在這個上下文的基礎上,和web MVC相干還會有1個上下文來保存控制器之類的MVC對象,這樣就構成了1個層次化的上下文結構。 從initWebApplicationContext中可以看到真正創建applicationContext容器是由createWebApplicationContext方法來實現的,它的代碼以下: protected WebApplicationContext createWebApplicationContext( ServletContext servletContext, ApplicationContext parent) throws BeansException { // 首先決定要創建的applicationContext容器的類 Class contextClass = determineContextClass(servletContext); // 如果獲得到的類不是ConfigurableWebApplicationContext類型的,則創建容器失敗,所以這里創建的容器必須是ConfigurableWebApplicationContext類型的 if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]"); } // 實例化spring容器 ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setParent(parent); wac.setServletContext(servletContext); // 獲得contextConfigLocation初始化參數,該參數記錄的是需要載入的多個配置文件(即定義bean的配置文件) String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM); if (configLocation != null) { wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation, ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS)); } wac.refresh(); return wac; }

createWebApplicationContext方法實現步驟為:

    1. 首先決定要創建的applicationContext容器的類
    2. 實例化applicationContext容器

    但它是如何決定要創建的容器類呢?我們看1下determineContextClass方法:

  

protected Class determineContextClass(ServletContext servletContext) throws ApplicationContextException { // 從web.xml中獲得需要初始化的容器的類名 String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM); // 如果獲得到的類名不為空,則創建該容器的Class對象 if (contextClassName != null) { try { return ClassUtils.forName(contextClassName); } catch (ClassNotFoundException ex) { throw new ApplicationContextException( "Failed to load custom context class [" + contextClassName + "]", ex); } } // 否則創建默許的容器的Class對象,即:org.springframework.web.context.support.XmlWebApplicationContext // 在創建ContextLoader時,defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);這句代碼已準備好默許的容器類 else { contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName()); try { return ClassUtils.forName(contextClassName); } catch (ClassNotFoundException ex) { throw new ApplicationContextException( "Failed to load default context class [" + contextClassName + "]", ex); } } }

該方法首先判斷從web.xml文件的初始化參數CONTEXT_CLASS_PARAM(的定義為public static final String CONTEXT_CLASS_PARAM = "contextClass";)獲得的的類名是不是存在,如果存在,則容器的Class;否則返回默許的Class。如何獲得默許的容器Class,注意看創建contextLoader時的代碼注釋就知道了。

    由此看來,spring不但有默許的applicationContext的容器類,還允許我們自定義applicationContext容器類,不過Spring不建義我們自定義applicationContext容器類。

  2、利用load-on-startup Servlet實現。

<servlet> <servlet-name>springServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

 



   好了,這就是spring的IoC容器在web容器如何啟動和起作用的全部進程。仔細的朋友可以看出創建applicationContext容器的同時會初始化配置文件中定義的bean類,createWebApplicationContext方法中的wac.refresh();這段代碼就是用來初始化配置文件中定義的bean類的。它具體的實現進程現在還沒完全弄清楚,等弄清楚了再跟大家分享!







生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 操操操网站 | 亚洲欧美日韩中文字幕在线一区 | 精品的一区二区三区 | 看一级毛片一区二区三区免费 | 羞羞色院91蜜桃在线观看 | 国产三级手机在线 | 毛片三级在线观看 | 99久久精品免费看国产漫画 | 亚洲最新视频 | 欧美性videosex18| 五月婷婷伊人 | 福利盒子手机看片 | 福利国产在线 | 五月婷婷激情四射 | 中文字幕在线视频播放 | 麻豆视传媒一区二区三区 | 久久国产免费一区二区三区 | 中文字幕一区二区三区永久 | 日本高清免费网站zzzzzzzz | 亚洲区欧美区 | 国产h肉在线视频免费观看 国产h视频 | 欧美性生活视频免费播放网址大全观看 | 最新国产在线观看福利 | 亚洲国产www| 欧美日韩亚洲第一页 | 久久国产免费一区二区三区 | 久久精品国产福利国产琪琪 | 亚洲人成网站在线播放942一 | 国产一区二区视频在线观看 | 日本三级成人午夜视频网 | 亚洲精品一区二区三区婷婷月 | 在线观看成年人免费视频 | 色性综合 | 日本乱人伦片中文三区 | 欧美成人网在线综合视频 | 亚洲综合图区 | 亚洲欧美一区二区三区久久 | 免费一级毛片清高播放 | 天堂俺去俺来也www久久婷婷 | 午夜在线视频观看版 | 亚洲人成伊人成综合网久久久 |