<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    樂(lè)在其中

    以JEE為主攻,以Flex為點(diǎn)綴,以Eclipse RCP為樂(lè)趣
    請(qǐng)?jiān)L問(wèn)http://www.inframesh.org

    首頁(yè) 新隨筆 聯(lián)系 管理
      43 Posts :: 0 Stories :: 8 Comments :: 0 Trackbacks

    Spring 和 Struts在web.xml中增加的配置:

       1: <!-- spring的配置 -->
       2: <context-param>
       3:     <param-name>contextConfigLocation</param-name>
       4:     <param-value>classpath:/SpringContext/applicationContext-web.xml</param-value>
       5: </context-param>    
       7:  
       8: <listener>
       9:     <listener-class>org.springframework.web.context.ContextLoaderListener
      10:     </listener-class>
      11: </listener>
      12:  
      13: <filter>
      14:     <filter-name>struts2</filter-name>
      15:     <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
      17:     <init-param>
      18:         <param-name>config</param-name>
      19:         <param-value>struts-default.xml,struts-plugin.xml,struts/struts.xml</param-value>
      20:     </init-param>
      21: </filter>
      22:  
      23: <filter-mapping>
      24:     <filter-name>struts2</filter-name>
      25:     <url-pattern>*.do</url-pattern>
      26: </filter-mapping>

     

    第一個(gè)tag定義的是spring的配置文件地址到環(huán)境參數(shù)(context parameter)

    第二個(gè)tag定義一個(gè)listener為org.springframework.web.context.ContextLoaderListener,這里相當(dāng)于j2ee容器給我們提供的main函數(shù)的切入點(diǎn),可以讓我們做一些系統(tǒng)初始化的工作,需要實(shí)現(xiàn)的類是:javax.servlet.ServletContextListener

    第三個(gè)tag則定義了struts2的一個(gè)filter。Filter則是對(duì)每次請(qǐng)求(可以通過(guò)filter-mapping指定)做過(guò)濾處理,請(qǐng)求首先請(qǐng)過(guò)filter鏈的處理,然后再到HttpServlet的init方法。對(duì)應(yīng)的類是:javax.servlet.Filter。上面先配置了一個(gè)filter,對(duì)應(yīng)的類是org.apache.struts2.dispatcher.FilterDispatcher,參數(shù)則是struts的配置文件位置

    第四個(gè)參數(shù)定義了filter怎樣行為,顯然它對(duì).do為后綴的請(qǐng)求應(yīng)用struts2這個(gè)名稱的filter

    這里需要首先搞清楚servlet規(guī)范中什么是listener?
     
    詳細(xì)請(qǐng)參見(jiàn) Servlet Listener和Filter

     

    查看ContextLoaderListener可知,它正好繼承了javax.servlet.ServletContextListener,用于監(jiān)聽(tīng)javax.servlet.ServletContextEvent事件

    /*
     * Copyright 2002-2007 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
     
    package org.springframework.web.context;
     
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
     
    /**
     * Bootstrap listener to start up Spring's root {@link WebApplicationContext}.
     * Simply delegates to {@link ContextLoader}.
     *
     * <p>This listener should be registered after
     * {@link org.springframework.web.util.Log4jConfigListener}
     * in <code>web.xml</code>, if the latter is used.
     *
     * @author Juergen Hoeller
     * @since 17.02.2003
     * @see ContextLoaderServlet
     * @see org.springframework.web.util.Log4jConfigListener
     */
    public class ContextLoaderListener implements ServletContextListener {
     
        private ContextLoader contextLoader;
     
     
        /**
         * Initialize the root web application context.
         */
        public void contextInitialized(ServletContextEvent event) {
            this.contextLoader = createContextLoader();
            this.contextLoader.initWebApplicationContext(event.getServletContext());
        }
     
        /**
         * Create the ContextLoader to use. Can be overridden in subclasses.
         * @return the new ContextLoader
         */
        protected ContextLoader createContextLoader() {
            return new ContextLoader();
        }
     
        /**
         * Return the ContextLoader used by this listener.
         * @return the current ContextLoader
         */
        public ContextLoader getContextLoader() {
            return this.contextLoader;
        }
     
     
        /**
         * Close the root web application context.
         */
        public void contextDestroyed(ServletContextEvent event) {
            if (this.contextLoader != null) {
                this.contextLoader.closeWebApplicationContext(event.getServletContext());
            }
        }
     
    }

    此類implement了ServletContextListener的兩個(gè)方法:

    public void contextInitialized(ServletContextEvent event);
    public void contextDestroyed(ServletContextEvent event);

    分別做context的初始化和銷毀

    另外提供了一個(gè)protected方法:protected ContextLoader createContextLoader()  用于創(chuàng)建真正做事情的代理類CotextLoader

    和一個(gè)public方法:public ContextLoader getContextLoader();

     

    可見(jiàn),這個(gè)Listener類直接將工作代理給了ContextLoader類了

     

    ____________________________________________________________________________________________________________________________

    我們按圖索驥,下面再分析org.springframework.web.context.ContextLoader

    ContextLoader里面有個(gè)私有成員:private WebApplicationContext context

    此變量提供了create方法:

    createWebApplicationContext(ServletContext servletContext, ApplicationContext parent)

    因?yàn)镾pring提供了多種WebApplicationContext類,所以需要一個(gè)方法來(lái)決定使用哪個(gè)WebApplicationContextContext類

    protected Class determineContextClass(ServletContext servletContext) throws ApplicationContextException {
            String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
            if (contextClassName != null) {
                try {
                    return ClassUtils.forName(contextClassName);
                }
                catch (ClassNotFoundException ex) {
                    throw new ApplicationContextException(
                            "Failed to load custom context class [" + contextClassName + "]", ex);
                }
            }
            else {
                contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
                try {
                    return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
                }
                catch (ClassNotFoundException ex) {
                    throw new ApplicationContextException(
                            "Failed to load default context class [" + contextClassName + "]", ex);
                }
            }
        }

     

    public static final String CONTEXT_CLASS_PARAM = "contextClass";

    所以如果在web.xml中的<context-param> </context-param>中定義了參數(shù)contextClass,那么直接就決定了用此Context類

    否則,就應(yīng)用缺省策略來(lái)決定使用哪個(gè)Context類。

    缺省策略如下:

    private static final Properties defaultStrategies;
     
    static {
        // Load default strategy implementations from properties file.
        // This is currently strictly internal and not meant to be customized
        // by application developers.
        try {
            ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
        }
        catch (IOException ex) {
            throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
        }
    }

    實(shí)際上,缺省策略從org\springframework\web\context\ContextLoader.properties 文件中取得屬性org.springframework.web.context.WebApplicationContext

    我們看看ContextLoader.properties文件的內(nèi)容:

    # Default WebApplicationContext implementation class for ContextLoader.
    # Used as fallback when no explicit context implementation has been specified as context-param.
    # Not meant to be customized by application developers.
     
    org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

    顯然,缺省的Context類就是 XmlWebApplicationContext類

    !!!真累啊,Spring...

     

    OK,總算知道用哪個(gè)Context類了,那么現(xiàn)在到了create這個(gè)Context實(shí)例的時(shí)候了

    protected WebApplicationContext createWebApplicationContext(
                ServletContext servletContext, ApplicationContext parent) throws BeansException {
     
            Class contextClass = determineContextClass(servletContext);
            if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
                throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
                        "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
            }
     
            ConfigurableWebApplicationContext wac =
                    (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
            wac.setParent(parent);
            wac.setServletContext(servletContext);
            wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));
            customizeContext(servletContext, wac);
            wac.refresh();
     
            return wac;
        }

    這里很容易理解,只不過(guò)它的創(chuàng)建不是直接new,而是封裝了一層,調(diào)用BeanUtils.instantiateClass()工具方法

    接下來(lái)設(shè)定WebApplicationCcontext實(shí)例的parent, servletContext,

    其中配置文件位置(web.xml中)的contextConfigLocation參數(shù)指定的

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/SpringContext/applicationContext-web.xml
        </param-value>
    </context-param>

    倒數(shù)第二行調(diào)用的customizeContext()方法目前Spring實(shí)現(xiàn)代碼是空的,估計(jì)留作以后(看來(lái)萬(wàn)事要留余地啊^_^)

    最后一件事就是調(diào)用WebApplicationContext的refresh()方法。(這個(gè)方法是個(gè)stratup方法,很重要。他干的事情后面會(huì)著重涉及)

     

    最后就是真正做事的initWebApplicationContext()方法:

    public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
                throws IllegalStateException, BeansException {
     
            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.
                this.context = createWebApplicationContext(servletContext, parent);
                servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
                currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), 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;
            }
        }

    它其實(shí)做得事情很簡(jiǎn)單,調(diào)用loadParentContext()方法獲取父context,調(diào)用createWebApplicationContext()創(chuàng)建WebApplicationContext實(shí)例

     

    一切都似乎完成了,至少我們明白了配置文件是如何加載進(jìn)去的,至于IoC容器如何幫你注入配置文件中的bean,下次再探索。線索是什么呢?你還記得在createWebApplication()的最后一步做什么了嗎?refresh(), 對(duì)了,這個(gè)就是你作為職業(yè)"嘿客"要探索的下一個(gè)線索

    posted on 2008-12-26 16:53 suprasoft Inc,. 閱讀(2633) 評(píng)論(1)  編輯  收藏 所屬分類: J2EE

    Feedback

    # re: 讀Spring源代碼之按圖索驥(一)Context創(chuàng)建與配置文件加載 2013-10-30 21:08 馬小龍
    真的很不錯(cuò)  回復(fù)  更多評(píng)論
      

    ©2005-2008 Suprasoft Inc., All right reserved.
    主站蜘蛛池模板: 91精品国产免费久久国语麻豆| 边摸边脱吃奶边高潮视频免费| 国产成人精品无码免费看| 亚洲人成网站色在线入口| 深夜a级毛片免费无码| 久久夜色精品国产亚洲av | 最新国产精品亚洲| 成人毛片免费观看视频大全| 亚洲熟妇无码一区二区三区导航| 中文字幕人成无码免费视频| 亚洲国产视频久久| 国产成人免费a在线视频色戒| 男女猛烈无遮掩视频免费软件 | 四虎永久免费影院| 免费夜色污私人影院网站| 亚洲日韩欧洲乱码AV夜夜摸| 免费在线黄色电影| 亚洲精品电影在线| 午夜精品在线免费观看| 男男gay做爽爽免费视频| 国产亚洲精AA在线观看SEE| 2021国内精品久久久久精免费| 亚洲一区精品视频在线| 成人免费无码精品国产电影| 一级人做人爰a全过程免费视频| 亚洲狠狠婷婷综合久久久久 | 日韩亚洲国产综合高清| 在线观看免费精品国产| 91视频免费观看| 激情五月亚洲色图| 久久久久国产亚洲AV麻豆| 成人午夜免费福利视频| 国产成人va亚洲电影| 亚洲av永久无码制服河南实里| 日本阿v免费费视频完整版| 自拍偷自拍亚洲精品播放| 不卡一卡二卡三亚洲| 18禁网站免费无遮挡无码中文| 黄色三级三级免费看| 久久精品国产亚洲av日韩| 免费国产精品视频|