Spring源码分析3----SpringMVC

    xiaoxiao2021-03-25  72

    Spring源码分析3----SpringMVC

    目录(?)[+]

    一、Web环境中的Spring MVC

        用大体上看,在使用Spring MVC的时候,需要在web.xml中配置DispatcherServlet,这个DispatcherServlet可以看成是一个前端控制器的具体实现,还需要在Bean定义中配置Web请求和COntroller(控制器)的对应关系,以及各种视图的展现方式。     Spring IoC是一个独立的模块,它并不是直接在Web容器中发挥作用的,如果要在Web环境中使用IoC容器,需要Spring为IoC设计一个启动过程,把IoC容器导入,并在Web容器中建立起来。具体来说,这个启动过程是和Web容器的启动过程集成在一起的。在这个过程中,一方面处理Web容器的启动,另一方面通过设计特定的Web容器拦截器,将IoC容器载入到Web环境中来,并将其初始化。在这个过程建立完成以后,IoC容器才能正常工作,而Spring MVC是建立是IoC容器的基础上的,这样才能建立起MVC框架的运行机制,从而响应从Web容器传递的HTTP请求。     下面以Tomcat作为Web容器的例子进行分析。

    [html]  view plain  copy   ……        <servlet>       <servlet-name>springmvc</servlet-name>       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>       <init-param>         <param-name>contextConfigLocation</param-name>         <param-value>classpath:/applicationContext.xml</param-value>       </init-param>       <load-on-startup>1</load-on-startup>       <async-supported>true</async-supported>     </servlet>     <servlet-mapping>       <servlet-name>springmvc</servlet-name>       <url-pattern>/</url-pattern>     </servlet-mapping>      <listener>       <listener-class>   org.springframework.web.context.ContextLoaderListener   </listener-class>   <listener>   ……       作为Spring MVC的启动类,ContextLoaderListener被定义为一个监听器,这个监听器是与Web服务器的生命周期相关联的,由ContextLoaderListener监听器负责完成IoC容器在Web环境中的启动工作。

    二、上下文在Web容器中的启动

    2.1.IoC容器启动的基本过程

        IoC容器的启动过程就是建立上下文的过程,该上下文是与ServletContext相伴而生的,同时也是IoC容器在Web应用环境中的具体表现之一。由ContextLoaderListener启动的上下文为根上下文。在根上下文的基础上,还有一个与Web MVC相碰的上下文 用来保持控制器(DispatchServlet)需要的MVC对象,作为根上下文的子上下文,构成一个层次化的上下文体系。在Web容器中启动Spring应用程序时,首先建立根上下文,然后建立这个上下文体系的,这个上下文体系的建立是由COntextLoader来完成的,具体过程由下:

    [java]  view plain  copy   public class ContextLoaderListener extends ContextLoader implements ServletContextListener {          public ContextLoaderListener() {       }          public ContextLoaderListener(WebApplicationContext context) {           super(context);       }          @Override       public void contextInitialized(ServletContextEvent event) {           initWebApplicationContext(event.getServletContext());  // ------->       }          @Override       public void contextDestroyed(ServletContextEvent event) {           closeWebApplicationContext(event.getServletContext());           ContextCleanupListener.cleanupAttributes(event.getServletContext());       }      }   [java]  view plain  copy   //-------------------------------   // ContextLoader       public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {           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!");           }              Log logger = LogFactory.getLog(ContextLoader.class);           servletContext.log("Initializing Spring root WebApplicationContext");           if (logger.isInfoEnabled()) {               logger.info("Root WebApplicationContext: initialization started");           }           long startTime = System.currentTimeMillis();              try {               // Store context in local instance variable, to guarantee that               // it is available on ServletContext shutdown.               if (this.context == null) {                   // ----------------------->                   this.context = createWebApplicationContext(servletContext);                }               if (this.context instanceof ConfigurableWebApplicationContext) {                   ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;                   if (!cwac.isActive()) {                       // The context has not yet been refreshed -> provide services such as                       // setting the parent context, setting the application context id, etc                       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);                       }                          // ------------------->                       configureAndRefreshWebApplicationContext(cwac, servletContext);                   }               }               servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);                  ClassLoader ccl = Thread.currentThread().getContextClassLoader();               if (ccl == ContextLoader.class.getClassLoader()) {                   currentContext = this.context;               }               else if (ccl != null) {                   currentContextPerThread.put(ccl, 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;           }       }             protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {           if (ObjectUtils.identityToString(wac).equals(wac.getId())) {               String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);               if (idParam != null) {                   wac.setId(idParam);               }               else {                   wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +                           ObjectUtils.getDisplayString(sc.getContextPath()));               }           }              wac.setServletContext(sc);           String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);           if (configLocationParam != null) {               wac.setConfigLocation(configLocationParam);           }              ConfigurableEnvironment env = wac.getEnvironment();           if (env instanceof ConfigurableWebEnvironment) {               ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);           }              customizeContext(sc, wac);           wac.refresh();   // ------------------>       }   [java]  view plain  copy   // -------------------------------------------------------   public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {          String CONFIG_LOCATION_DELIMITERS = ",; \t\n";       String CONVERSION_SERVICE_BEAN_NAME = "conversionService";       String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";       String ENVIRONMENT_BEAN_NAME = "environment";       String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";       String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";          void setId(String id);          void setParent(ApplicationContext parent);          @Override       ConfigurableEnvironment getEnvironment();          void setEnvironment(ConfigurableEnvironment environment);          void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);          void addApplicationListener(ApplicationListener<?> listener);          void addProtocolResolver(ProtocolResolver resolver);          // --------------------->       void refresh() throws BeansException, IllegalStateException;          void registerShutdownHook();          @Override       void close();          boolean isActive();          ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;      }   [java]  view plain  copy   //------------------------------------------------------------   // public abstract class AbstractApplicationContext extends DefaultResourceLoader   //      implements ConfigurableApplicationContext, DisposableBean          @Override       public void refresh() throws BeansException, IllegalStateException {           synchronized (this.startupShutdownMonitor) {               prepareRefresh();               ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();               prepareBeanFactory(beanFactory);                  try {                   postProcessBeanFactory(beanFactory);                   invokeBeanFactoryPostProcessors(beanFactory);                   registerBeanPostProcessors(beanFactory);                   initMessageSource();                   initApplicationEventMulticaster();                   onRefresh();                   registerListeners();                   finishBeanFactoryInitialization(beanFactory);                   finishRefresh();               }               catch (BeansException ex) {                   if (logger.isWarnEnabled()) {                       logger.warn("Exception encountered during context initialization - " +                               "cancelling refresh attempt: " + ex);                   }                      destroyBeans();                   cancelRefresh(ex);                   throw ex;               }               finally {                   resetCommonCaches();               }           }       }       在Web.xml,已经配置了ContextLoaderListener,这个ContextLoaderListener是Spring提供的类,是为在Web容器中建立IoC容器服务的,它实现了ServletContextListener接口,这个接口提供了与Servlet生命周期的回调。而在Web容器中,建立WebApplicationContext的过程,是在contextInitialized的接口实现中完成的。具体的载入IoC容器的过程是由ContextLoaderListener交由ContextLoaderg来完成的,而ContextLoader本身就是ContextLoaderListener的基类。     在ContextLoader中,完成了两个IoC容器建立的基本过程,一个是在Web容器中建立起双亲IoC容器,另一个是生成相应的WebApplicationContext并将其初始化。 转载出处:http://blog.csdn.net/oChangWen/article/details/61414380
    转载请注明原文地址: https://ju.6miu.com/read-36196.html

    最新回复(0)