spring启动过程之源码跟踪(下)--spring Debug

 2019-11-02 21:21  阅读(1687)
文章分类:Spring boot

spring启动过程之源码跟踪(下)–spring Debug

在web应用启动入口是ContextLoaderListener,它是怎么完成启动过程的呢?

首先:

20191102100731\_1.png

public class ContextLoaderListenerextends Object implements ServletContextListener

    //Bootstrap listener to start up Spring's root WebApplicationContext. Simply delegates to ContextLoader.

    //This listener should be registered after Log4jConfigListener in web.xml, if the latter is used.

    public abstract interface javax.servlet.ServletContextListener extends java.util.EventListener

20191102100731\_2.png

1.ContextLoaderListener.java

1     public void contextInitialized(ServletContextEvent event) {
    2         this.contextLoader = createContextLoader();
    3         this.contextLoader.initWebApplicationContext(event.getServletContext());
    4     }

2.ContextLoader.java

20191102100731\_3.png

1     /**
     2      * Initialize Spring's web application context for the given servlet context,
     3      * according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
     4      * "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
     5      * @param servletContext current servlet context
     6      * @return the new WebApplicationContext
     7      * @throws IllegalStateException if there is already a root application context present
     8      * @throws BeansException if the context failed to initialize
     9      * @see #CONTEXT_CLASS_PARAM
    10      * @see #CONFIG_LOCATION_PARAM
    11      */
    12     public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
    13             throws IllegalStateException, BeansException {
    14 
    15         if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
    16             throw new IllegalStateException(
    17                     "Cannot initialize context because there is already a root application context present - " +
    18                     "check whether you have multiple ContextLoader* definitions in your web.xml!");
    19         }
    20 
    21         servletContext.log("Initializing Spring root WebApplicationContext");
    22         if (logger.isInfoEnabled()) {
    23             logger.info("Root WebApplicationContext: initialization started");
    24         }
    25         long startTime = System.currentTimeMillis();
    26 
    27         try {
    28             // Determine parent for root web application context, if any.
    29             ApplicationContext parent = loadParentContext(servletContext);
    30 
    31             // Store context in local instance variable, to guarantee that
    32             // it is available on ServletContext shutdown.
    33             this.context = createWebApplicationContext(servletContext, parent);
    34             servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
    35             currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
    36 
    37             if (logger.isDebugEnabled()) {
    38                 logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
    39                         WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
    40             }
    41             if (logger.isInfoEnabled()) {
    42                 long elapsedTime = System.currentTimeMillis() - startTime;
    43                 logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
    44             }
    45 
    46             return this.context;
    47         }
    48         catch (RuntimeException ex) {
    49             logger.error("Context initialization failed", ex);
    50             servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
    51             throw ex;
    52         }
    53         catch (Error err) {
    54             logger.error("Context initialization failed", err);
    55             servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
    56             throw err;
    57         }
    58     }

20191102100731\_4.png

3.ContextLoader.java

20191102100731\_5.png

1     protected WebApplicationContext createWebApplicationContext(
     2             ServletContext servletContext, ApplicationContext parent) throws BeansException {
     3 
     4         Class contextClass = determineContextClass(servletContext);
     5         if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
     6             throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
     7                     "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
     8         }
     9 
    10         ConfigurableWebApplicationContext wac =
    11                 (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
    12         wac.setParent(parent);
    13         wac.setServletContext(servletContext);
    14         wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));
    15         customizeContext(servletContext, wac);
    16         wac.refresh();
    17 
    18         return wac;
    19     }

20191102100731\_6.png

4.回到了我们上两节提到的AbstractApplicationContext.java

20191102100731\_7.png

public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();

                // Tell the subclass to refresh the internal bean factory.
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);

                try {
                    // Allows post-processing of the bean factory in context subclasses.
                    postProcessBeanFactory(beanFactory);

                    // Invoke factory processors registered as beans in the context.
                    invokeBeanFactoryPostProcessors(beanFactory);

                    // Register bean processors that intercept bean creation.
                    registerBeanPostProcessors(beanFactory);

                    // Initialize message source for this context.
                    initMessageSource();

                    // Initialize event multicaster for this context.
                    initApplicationEventMulticaster();

                    // Initialize other special beans in specific context subclasses.
                    onRefresh();

                    // Check for listener beans and register them.
                    registerListeners();

                    // Instantiate all remaining (non-lazy-init) singletons.
                    finishBeanFactoryInitialization(beanFactory);

                    // Last step: publish corresponding event.
                    finishRefresh();
                }

                catch (BeansException ex) {
                    // Destroy already created singletons to avoid dangling resources.
                    beanFactory.destroySingletons();

                    // Reset 'active' flag.
                    cancelRefresh(ex);

                    // Propagate exception to caller.
                    throw ex;
                }
            }
        }

20191102100731\_8.png


来源:http://ddrv.cn

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> spring启动过程之源码跟踪(下)--spring Debug

相关推荐