Spring上下文在web容器中的启动过程
2017-06-26 00:00
190 查看
摘要: Spring上下文在web容器中的启动
Spring上下文在web容器中的启动过程,简单地说,就是包括IoC容器启动的基本过程和Web容器的初始化并启动的过程.
IoC容器的启动过程就是建立上下文的过程,该上下文是与ServletContext相伴而生的,同时也是IoC容器在Web应用环境中的具体表现之一。由ContextLoaderListener启动的上下文为根上下文。
Spring应用在Web容器中启动的整个过程如下:
按上图的步骤,各个部分细节如下:
1. 在ContextLoaderListener中,实现的是ServletContextListener接口,这个接口里的函数会结合Web容器的生命周期被调用。因为ServletContextListener是ServletContext的监听者,如果ServletContext发生变化,会触发出相应的事件,而监听器一直在对这些事件进行监听,如果接收到了监听的事件,就会做出预先设计好的响应动作。由于ServletContext的变化而触发的监听器的响应具体包括:在服务器启动时,ServletContext被创建的时候;服务器关闭时,ServletContext将被销毁的时候等。对应这些事件及Web容器状态的变化,在监听器中定义了对应的事件响应的回调方法。比如在服务器启动时,ServletContextListener的contextInitialized()方法被调用,服务器将要关闭时,ServletContextLis-tener的contextDestroyed()方法被调用.
2.在Web容器中,建立WebApplicationContext的过程,是在contextInitialized的接口实现中完成的。
contextInitialized就是调用initWebApplicationContext,所以也可以合为一步. 具体的载入IoC容器的过程是由ContextLoaderListener交由ContextLoader来完成的 .
在web.xml中,已经配置了ContextLoaderListener,这个ContextLoaderListener是Spring提供的类,是为在Web容器中建立IoC容器服务的,它实现了ServletContextListener接口。这个监听器主要功能是启动根IoC容器并把它载入到Web容器的主要功能模块,也是整个Spring Web应用加载IoC的第一个地方。从加载过程可以看到,首先从Servlet事件中得到ServletContext,然后可以读取配置在web.xml中的各个相关的属性值,接着ContextLoader会实例化WebApplicationContext,并完成其载入和初始化过程。这个被初始化的第一个上下文作为根上下文而存在,这个根上下文载入后,被绑定到Web应用程序的ServletContext上。任何需要访问根上下文的应用程序代码都可以从WebApplicationContextUtils类的静态方法中得到,具体取得根上下文的方法如下所示:
3.在ContextLoader中,完成了两个IoC容器建立的基本过程,一个是在Web容器中建立起双亲IoC容器,另一个是生成相应的WebApplicationContext并将其初始化。
具体的初始化工作交给ContextLoader来完成,代码如下所示:
在这个初始化过程中,完成根上下文在Web容器中的创建。这个根上下文是作为Web容器中唯一的实例而存在的,如果在这个初始化过程中,发现已经有根上下文被创建了,这里会抛出异常提示创建失败。
4.完成这些基本的设置以后,通过对refresh方法的调用,重启整个IoC容器,就像一般的IoC容器的初始化过程一样.
5.根上下文创建成功以后,会被存到Web容器的ServletContext中去,供需要时使用。
特别提醒:
应用可以在部署描述符中指定使用什么样的IoC容器,这个指定操作是通过CONTEXT_CLASS_PARAM参数的设置完成的。如果没有指定特定的IoC容器,将使用默认的IoC容器,也就是XmlWebApplicationContext对象作为在Web环境中使用的IoC容器。
Spring上下文在web容器中的启动过程,简单地说,就是包括IoC容器启动的基本过程和Web容器的初始化并启动的过程.
IoC容器的启动过程就是建立上下文的过程,该上下文是与ServletContext相伴而生的,同时也是IoC容器在Web应用环境中的具体表现之一。由ContextLoaderListener启动的上下文为根上下文。
Spring应用在Web容器中启动的整个过程如下:
按上图的步骤,各个部分细节如下:
1. 在ContextLoaderListener中,实现的是ServletContextListener接口,这个接口里的函数会结合Web容器的生命周期被调用。因为ServletContextListener是ServletContext的监听者,如果ServletContext发生变化,会触发出相应的事件,而监听器一直在对这些事件进行监听,如果接收到了监听的事件,就会做出预先设计好的响应动作。由于ServletContext的变化而触发的监听器的响应具体包括:在服务器启动时,ServletContext被创建的时候;服务器关闭时,ServletContext将被销毁的时候等。对应这些事件及Web容器状态的变化,在监听器中定义了对应的事件响应的回调方法。比如在服务器启动时,ServletContextListener的contextInitialized()方法被调用,服务器将要关闭时,ServletContextLis-tener的contextDestroyed()方法被调用.
2.在Web容器中,建立WebApplicationContext的过程,是在contextInitialized的接口实现中完成的。
contextInitialized就是调用initWebApplicationContext,所以也可以合为一步. 具体的载入IoC容器的过程是由ContextLoaderListener交由ContextLoader来完成的 .
public void contextInitialized(ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); }
在web.xml中,已经配置了ContextLoaderListener,这个ContextLoaderListener是Spring提供的类,是为在Web容器中建立IoC容器服务的,它实现了ServletContextListener接口。这个监听器主要功能是启动根IoC容器并把它载入到Web容器的主要功能模块,也是整个Spring Web应用加载IoC的第一个地方。从加载过程可以看到,首先从Servlet事件中得到ServletContext,然后可以读取配置在web.xml中的各个相关的属性值,接着ContextLoader会实例化WebApplicationContext,并完成其载入和初始化过程。这个被初始化的第一个上下文作为根上下文而存在,这个根上下文载入后,被绑定到Web应用程序的ServletContext上。任何需要访问根上下文的应用程序代码都可以从WebApplicationContextUtils类的静态方法中得到,具体取得根上下文的方法如下所示:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); //ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE是默认的路径 }
3.在ContextLoader中,完成了两个IoC容器建立的基本过程,一个是在Web容器中建立起双亲IoC容器,另一个是生成相应的WebApplicationContext并将其初始化。
具体的初始化工作交给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; } }
在这个初始化过程中,完成根上下文在Web容器中的创建。这个根上下文是作为Web容器中唯一的实例而存在的,如果在这个初始化过程中,发现已经有根上下文被创建了,这里会抛出异常提示创建失败。
4.完成这些基本的设置以后,通过对refresh方法的调用,重启整个IoC容器,就像一般的IoC容器的初始化过程一样.
5.根上下文创建成功以后,会被存到Web容器的ServletContext中去,供需要时使用。
特别提醒:
应用可以在部署描述符中指定使用什么样的IoC容器,这个指定操作是通过CONTEXT_CLASS_PARAM参数的设置完成的。如果没有指定特定的IoC容器,将使用默认的IoC容器,也就是XmlWebApplicationContext对象作为在Web环境中使用的IoC容器。
相关文章推荐
- 【Java.Spring.MVC】Spring在Web容器中的启动过程
- Spring 在web 容器中的启动过程
- Spring在Web容器中的启动过程
- spring源码研究之IoC容器在web容器中初始化过程(转)
- spring源码研究之IoC容器在web容器中初始化过程
- spring技术内幕10-Web环境中Spring启动过程
- Spring容器启动过程
- spring在web容器启动时执行初始化方法
- spring(2) spring ioc容器在Web容器中的启动
- Web环境中Spring的启动过程
- spring容器 的启动过程
- apacheFtpServer集成spring由web容器控制启动和关闭
- Web环境中Spring的启动过程
- Web容器启动时加载Spring的配置
- 《Spring技术内幕》学习笔记10——Web环境中Spring的启动过程
- 从源码看spring applicationContext在web容器中加载过程
- Spring IoC容器在Web环境中的启动源码阅读
- Spring源代码分析之(二):IOC容器在web容器中的启动
- Spring源代码解析(二):IoC容器在Web容器中的启动
- 从源码看spring applicationContext在web容器中加载过程