Web上下文:
Web上下文又称为ServletContext,ServletContext是Servlet容器上下文环境对象,定义了一组方法,servlet 使用这些方法与其 servlet 容器进行通信,例如,获取文件的 MIME 类型、分发请求或写入日志文件。每个web应用都有且仅有一个ServletContext对象,这个对象在所有的Servlet都可以使用。
web 容器提供的全局上下文环境,为后面的 Spring IOC 提供宿主环境。
Spring上下文:
继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持、资源访问(如URL和文件)、事件传播等方面进行了良好的支持,被推荐为Java EE应用之首选,可应用在Java APP与Java Web中。
由web.xml中提供的 contextLoaderListener,在web容器启动时触发容器初始化事件,其中的 contextInitialized 方法被调用时创建的根上下文(即:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,)。采用 XmlWebApplicationContext 实现方法,作为 Spring IOC 容器,对应的 Bean 定义的配置由 web.xml 中的 context-param 标签指定。会被存储在 ServletContext 中。
SpringMvc上下文
获取根上下文(WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE ) 作为自己上下文的parent上下文,再初始化自己持有的上下文(默认实现类也是 xmlWebApplicationContext)。之后将该上下文以key-value的方式设置在 ServletContex中,以便后续使用。至此,每个 Servlet 既有自己的上下文(即独立的bean空间),又各个 Servlet 可以共享根上下文中定义的 bean。
例如:DispatcherServlet 维持自己的 ApplicationContext,默认会读取/WEB-INFO/-servlet.xml 文件,也可以在 /WEB-INF/web.xml 中的 Servlet 模块 重新配置。
参考博客:https://blog.csdn.net/cathar/article/details/54880875
我自己的理解是:
在应用项目启动的时候呢,web容器给项目初始化一个ervletContext作为公共环境容器存放公共信息。ServletContext中的信息都是由容器提供的。
执行流程:
web.xml在<context-param></context-param>标签中声明应用范围内的初始化参数
1.启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> 和 <context-param></context-param> 2.紧接着,容器创建一个ServletContext(上下文)。在该应用内全局共享。
3.容器将<context-param></context-param>转化为键值对,并交给ServletContext.
4.容器创建<listener></listener>中的类实例,即创建监听.该监听器必须实现自ServletContextListener接口
5.在监听中会有contextInitialized(ServletContextEvent event)初始化方法,在这个方法中获得 ServletContext=ServletContextEvent.getServletContext(); “context-param的值” = ServletContext.getInitParameter('context-param的键');
6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早.换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行.web.xml中可以定义两种参数:
(1)一个是全局参数(ServletContext),通过<context-param></context-param>
例如:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
一个是servlet参数,通过在servlet中 <init-param> 标签中通过<param-name><param-value>
例如:
<servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置springMVC需要加载的配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-*.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet>
第一种参数在servlet里面可以通过getServletContext().getInitParameter('context/param')得到
第二种参数只能在servlet的init()方法中通过this.getInitParameter('param1')取得
初始化Spring上下文:
然后Spring为我们提供了一个接口来初始化Spring上下文:org.springframework.web.context.ContextLoaderListener
使用方法:
<!-- spring的配置文件--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
该监听器,默认读取/WEB-INF/下的applicationContext.xml文件。但是通过context-param指定配置文件路径后,便会去你指定的路径下读取对应的配置文件,并进行初始化。
即从上述的第二步开始:
容器调用web.xml中配置的contextLoaderListener,初始化WebApplicationContext上下文环境(即IOC容器),加载context-param指定的配置文件信息到IOC容器中。WebApplicationContext在ServletContext中以键值对的形式保存
这时候我们的web应用就有了我们的SpringIOC容器
还没完呢,不是还有SpringMVC容器吗?
初始化SpringMvc上下文:
<!-- 配置DispatcherServlet --> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置springMVC需要加载的配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-*.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet>
容器为其初始化自己的上下文信息servletContext,并加载其设置的配置信息到该上下文中。将WebApplicationContext设置为它的父容器,即springmvc以及后面的servlet都是springIoc容器的子容器。
这三者的关系就像我下面画的这副图
最后借博客总结:https://blog.csdn.net/cathar/article/details/54880875
1.功能而言:ContextLoaderListener中创建ApplicationContext(SpringIoc上下文)主要用于整个Web应用程序需要共享的一些组件,不管是使用什么表现层技术,一般如DAO层、Service层Bean、数据库的ConnectionFactory等。而由DispatcherServlet创建的ApplicationContext 只加载对Spring Web MVC有效的Bean,如Controller、HandlerMapping、HandlerAdapter等等,该初始化上下文应该只加载Web相关组件。
2.范围而言:在DispatcherServlet(SpringMVC上下文)中可以引用由ContextLoaderListener所创建的ApplicationContext(SpringIoc上下文),而反过来不行。
实现顺序:这两个ApplicationContext都是通过ServletContext的setAttribute方法放到ServletContext中的。但是,ContextLoaderListener会先于DispatcherServlet(SpringMVC上下文)创建ApplicationContext,DispatcherServlet在创建ApplicationContext时会先找到由ContextLoaderListener所创建的ApplicationContext(SpringIoc上下文),再将后者的ApplicationContext(SpringIoc上下文)作为参数传给DispatcherServlet的ApplicationContext的setParent()方法。此后,框架又会调用ServletContext的setAttribute()方法将wac加入到ServletContext中。
3.查找顺序:当Spring在执行ApplicationContext的getBean时,如果在自己context中找不到对应的bean,则会在父ApplicationContext中去找。这也解释了为什么我们可以在DispatcherServlet中获取到由ContextLoaderListener对应的ApplicationContext中的bean。