SpringはTomcat起動時にどうやって起動しますか?

7047 ワード

私達がspringを使ってtomcatと結合する時、私達はいずれもResourceファイルの下でwebapp/WEB-INFフォルダの下にweb.xmlファイルを作成します.このファイルにこのような構成を追加します.
  
    
        org.springframework.web.context.ContextLoaderListener
    
  
この設定を加えるとTomcatは起動時にweb.xmlファイルの中の2つの結点を読みに行きます.続いて、Servlet Contectを作成します.このウェブプロジェクトのすべての部分はこのコンテキストを共有して、キーペアに変換して、servlet Contextに渡します.また、クラスのインスタンスを作成し、モニターを作成します.このとき、Contect LoaderListenerクラスが作成されます.Webアプリケーションのフィルタまたはservletを初期化する前に、クラスのcontext Initializedメソッドを呼び出します.
    public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
    }
この方法は所与のservletコンテキストのためにSpringのWebアプリケーションコンテキストを初期化し、内部に呼び出されたinitWebAppliation Conteet方法に入ります.この方法はContect Loader Listenerの親タイプContect Loaderに定義されています.
public class ContextLoader {
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        ...
        try {
            //  WebApplicationContext  null,    web.xml        ,   null,       ContextLoaderListener        
            if (this.context == null) {
                //  WebApplicationContext
                this.context = createWebApplicationContext(servletContext);
            }
            //  WebApplicationContext ConfigurableWebApplicationContext            
            if (this.context instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
                //             ,               false,        ,     true
                if (!cwac.isActive()) {
                    // The context has not yet been refreshed -> provide services such as  setting the parent context, setting the application context id, etc
                    //           ,  servletContext       ,                 
                    if (cwac.getParent() == null) {
                        // The context instance was injected without an explicit parent ->  determine parent for root web application context, if any.
                        ApplicationContext parent = loadParentContext(servletContext);
                        cwac.setParent(parent);
                    }
                    //        ,  servletContext        spring     ,          servlet initParam      
                    configureAndRefreshWebApplicationContext(cwac, servletContext);
                }
            }
            // spring       servletContext 
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
            ClassLoader ccl = Thread.currentThread().getContextClassLoader();
            if (ccl == ContextLoader.class.getClassLoader()) {
                currentContext = this.context;
            }
            //              ,     ServletContext     
            else if (ccl != null) {
                currentContextPerThread.put(ccl, this.context);
            }
            if (logger.isInfoEnabled()) {
                long elapsedTime = System.currentTimeMillis() - startTime;
                logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms");
            }

            return this.context;
            }
        ...
    }
}
私たちはxmlの形式でlistenerを配置する時、デフォルトのWebApple Conteetはnullです.この時自動的にWebAppliation Conteetを作成しますので、createWebApplication Contextの方法に入ります.
    protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
    //  ServletContext   WebApplicationContext Class  
        Class> contextClass = determineContextClass(sc);
        if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
            throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
                    "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
        }
        //   WebApplicationContext
        return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
    }
 次はdetermine Contact Class方法に入ります.
    protected Class> determineContextClass(ServletContext servletContext) {
        //     WebApplicationContext    contextClass  ,        
        String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
        //           
        if (contextClassName != null) {
            try {
                return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
            }
            catch (ClassNotFoundException ex) {
                throw new ApplicationContextException(
                        "Failed to load custom context class [" + contextClassName + "]", ex);
            }
        }
        else {
            // defaultStrategies      WebApplicationContext ClassName
            contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
            try {
                //  contextClassName  Class  
                return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
            }
            catch (ClassNotFoundException ex) {
                throw new ApplicationContextException(
                        "Failed to load default context class [" + contextClassName + "]", ex);
            }
        }
    }   
一般的にServlet Contactクラスのcontext Classの構成は設定されませんので、ここではデフォルト値を使ってdefault Strategiesの対象に入ります.このオブジェクトはContact Loaderの静的コードブロックで初期化されていることが分かりました.
        private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
    static {
        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());
        }
    }
 default Strategiesの値はプロファイルContect Loader.propertiesから取得したものと見られますので、直接ファイルを開けて確認することができます.
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
ここに来て、デフォルトの実装を知っています.WebApplication ComptextはXml WebApplication Comptextです.文脈例が作成された以上、次は更新されます.ここではinitWebAppleicationContectメソッドで呼び出されたconfigreAndRefresh WebAppleication Comptext方法に入ります.主にその中のrefsh方法を見ます.
    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
    ...
    //                  ,    ServletContext spring     ,  
    //     
    wac.refresh();
    ...
    }
ここでSpringを開く容器の刷新がコアです.ここで呼び出されたのはAbstractAplicationControtext類のrefreshです.この前に5.2 Springソース解析――refsh方法について説明しました.後でloadBenDefinitionsメソッドを呼び出す時に呼び出したのはXmlWebAppleication ContextのloadBenDefinitionsです.