Spring Framework本身没有Web功能,Spring MVC使用WebApplicationContext类扩展ApplicationContext,使得拥有web功能。那么,Spring MVC是如何在web环境中创建IoC容器呢?web环境中的IoC容器的结构又是什么结构呢?web环境中,spring IoC容器是怎么启动呢?
先看一下WebApplicationContext是如何扩展ApplicationContext来添加对Web环境的支持的。WebApplicationContext接口定义如下:
- public interface WebApplicationContext extends ApplicationContext {
- //根上下文在ServletContext中的名称
- String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
- //取得web容器的ServletContext
- ServletContext getServletContext();
- }
对于web容器中创建IoC容器的过程,我们从web.xml配置文件讲起。看一下Spring MVC的web.xml中的相关配置:
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/WEB-INF/applicationContext.xml</param-value>
- </context-param>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- Handles all requests into the application -->
- <servlet>
- <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/spring/*.xml
- </param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <!-- Maps all /app requests to the DispatcherServlet for handling -->
- <servlet-mapping>
- <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
- <url-pattern>/app/*</url-pattern>
- </servlet-mapping>
在web.xml配置文件中,有两个主要的配置:ContextLoaderListener和DispatcherServlet。同样的关于spring配置文件的相关配置也有两部分:context-param和DispatcherServlet中的init-param。那么,这两部分的配置有什么区别呢?它们都担任什么样的职责呢?
在Spring MVC中,Spring Context是以父子的继承结构存在的。Web环境中存在一个ROOT Context,这个Context是整个应用的根上下文,是其他context的双亲Context。同时Spring MVC也对应的持有一个独立的Context,它是ROOT Context的子上下文。
对于这样的Context结构在Spring MVC中是如何实现的呢?下面就先从ROOT Context入手,ROOT Context是在ContextLoaderListener中配置的,ContextLoaderListener读取context-param中的contextConfigLocation指定的配置文件,创建ROOT Context。下面看一下ContextLoaderListener中创建context的源码:
- /**
- * Initialize Spring's web application context for the given servlet context,
- * according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
- * "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
- * @param servletContext current servlet context
- * @return the new WebApplicationContext
- * @see #CONTEXT_CLASS_PARAM
- * @see #CONFIG_LOCATION_PARAM
- */
- public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
- //PS : ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE=WebApplicationContext.class.getName() + ".ROOT" 根上下文的名称
- //PS : 默认情况下,配置文件的位置和名称是: DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"
- //在整个web应用中,只能有一个根上下文
- 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 {
- // Determine parent for root web application context, if any.
- ApplicationContext parent = loadParentContext(servletContext);
- // Store context in local instance variable, to guarantee that
- // it is available on ServletContext shutdown.
- // 在这里执行了创建WebApplicationContext的操作
- this.context = createWebApplicationContext(servletContext, parent);
- //PS: 将根上下文放置在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;
- }
- }
再看一下WebApplicationContext对象是如何创建的:
- protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) {
- //根据web.xml中的配置决定使用何种WebApplicationContext。默认情况下使用XmlWebApplicationContext
- //web.xml中相关的配置context-param的名称“contextClass”
- 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的实现类
- ConfigurableWebApplicationContext wac =
- (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
- // Assign the best possible id value.
- if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
- // Servlet <= 2.4: resort to name specified in web.xml, if any.
- String servletContextName = sc.getServletContextName();
- if (servletContextName != null) {
- wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + servletContextName);
- }
- else {
- wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX);
- }
- }
- else {
- // Servlet 2.5's getContextPath available!
- wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + sc.getContextPath());
- }
- wac.setParent(parent);
- wac.setServletContext(sc);
- //设置spring的配置文件
- wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));
- customizeContext(sc, wac);
- //spring容器初始化
- wac.refresh();
- return wac;
- }
以上是web容器中根上下文的加载与初始化,下面介绍一下Spring MVC对应的上下文是如何加载的。
Spring MVC中核心的类是DispatcherServlet,在这个类中完成Spring context的加载与创建,并且能够根据Spring Context的内容将请求分发给各个Controller类。DispatcherServlet继承自HttpServlet,关于Spring Context的配置文件加载和创建是在init()方法中进行的,主要的调用顺序是init-->initServletBean-->initWebApplicationContext。
先来看一下initWebApplicationContext的实现
- /**
- * Initialize and publish the WebApplicationContext for this servlet.
- * <p>Delegates to {@link #createWebApplicationContext} for actual creation
- * of the context. Can be overridden in subclasses.
- * @return the WebApplicationContext instance
- * @see #setContextClass
- * @see #setContextConfigLocation
- */
- protected WebApplicationContext initWebApplicationContext() {
- //先从web容器的ServletContext中查找WebApplicationContext
- WebApplicationContext wac = findWebApplicationContext();
- if (wac == null) {
- // No fixed context defined for this servlet - create a local one.
- //从ServletContext中取得根上下文
- WebApplicationContext parent =
- WebApplicationContextUtils.getWebApplicationContext(getServletContext());
- //创建Spring MVC的上下文,并将根上下文作为起双亲上下文
- wac = createWebApplicationContext(parent);
- }
- if (!this.refreshEventReceived) {
- // Apparently not a ConfigurableApplicationContext with refresh support:
- // triggering initial onRefresh manually here.
- onRefresh(wac);
- }
- if (this.publishContext) {
- // Publish the context as a servlet context attribute.
- // 取得context在ServletContext中的名称
- String attrName = getServletContextAttributeName();
- //将Spring MVC的Context放置到ServletContext中
- getServletContext().setAttribute(attrName, wac);
- if (this.logger.isDebugEnabled()) {
- this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
- "' as ServletContext attribute with name [" + attrName + "]");
- }
- }
- return wac;
- }
通过initWebApplicationContext方法的调用,创建了DispatcherServlet对应的context,并将其放置到ServletContext中,这样就完成了在web容器中构建Spring IoC容器的过程。
最后,在分别给出ContextLoaderListener和DispatcherServlet构建context的时序。
ContextLoaderListener构建Root Context时序图:
DispatcherServlet创建context时序图:
http://blog.csdn.net/prince2270/article/details/5889117
相关推荐
1.1 容器的构建与初始化 在实现中,我们可以创建一个`ApplicationContext`类作为容器,它负责读取配置文件(如XML或Java注解),解析并生成bean的定义。 1.2 Bean的定义与实例化 bean的定义通常包含类名、属性和...
通过XML或注解方式声明bean,Spring可以自动管理bean的实例化、初始化和销毁,从而简化了代码并提高了可测试性。 其次,Spring的面向切面编程(AOP)允许开发者将关注点分离,比如日志、事务管理等横切关注点,从...
4. **初始化**:Spring容器调用Bean的初始化方法,完成对象的初始化。 5. **Bean管理**:Spring容器负责Bean的生命周期管理,包括销毁等操作。 **六、应用场景** Spring Ioc广泛应用于各种项目中,如: - 数据...
这个过程涉及到一系列的初始化步骤,确保Spring能够正确地与Web容器集成。 首先,`WebApplicationContext`是`ApplicationContext`的一个扩展,专门针对Web应用设计。它增加了对`ServletContext`的访问和管理,使得...
标题 "Spring3.1.3 Ioc在Web容器中的建立" 涉及的是Spring框架的一个关键特性——依赖注入(Dependency Injection,简称DI),以及如何在Web应用环境中配置和使用它。Spring是Java开发中最流行的轻量级框架之一,...
2. **Spring Bean的生命周期**:了解Bean的初始化、销毁方法,以及如何自定义Bean的生命周期。 3. **注解驱动的Spring MVC**:使用@Controller、@RequestMapping等注解来定义控制器及URL映射。 4. **Spring JDBC ...
Spring的IOC(Inversion of Control,控制反转)容器是其核心特性之一,它负责管理和装配应用程序中的对象。本文将深入探讨如何实现一个简单的Spring IOC容器,以及涉及的主要知识点。 首先,控制反转是一种设计...
- 在 Web 容器启动时,会调用 `HttpServletBean` 的 `init()` 方法,初始化 Servlet 初始化参数。 - 接着调用 `FrameworkServlet` 的 `initServletBean()` 方法进行 Web 上下文初始化。 - 最后,`...
1. **web.xml**:这是部署描述符,定义了DispatcherServlet的配置,包括Servlet的映射路径和初始化参数。例如,配置DispatcherServlet的servlet-name、url-pattern以及加载Spring MVC的配置文件。 2. **spring-mvc-...
1. Spring框架的配置和使用,包括IoC容器的初始化、bean的定义和依赖注入。 2. Spring MVC的控制器定义、模型绑定、视图解析,以及处理HTTP请求的方法。 3. MyBatis的配置,SQL映射文件的编写,以及如何通过MyBatis...
- `web.xml`:配置DispatcherServlet和ContextLoaderListener,前者处理HTTP请求,后者初始化Spring的ApplicationContext。 - `spring-mvc.xml`:配置ViewResolver,比如InternalResourceViewResolver,用于解析...
DispatcherServlet也初始化了一个WebApplicationContext,它是Spring容器的一个特殊版本,专门用于Web应用。 2. **IoC(Inversion of Control)容器**:Spring MVC中的Controller组件是JavaBean,它们的实例化、...
然后,配置Spring的IoC容器,包括定义bean的实例化方式、初始化参数等。接着,设置Spring MVC的配置,如处理器映射器、视图解析器等。最后,配置Hibernate连接数据库的相关信息,包括数据源、实体类、映射文件等。 ...
6. **spring-beans-4.1.5.RELEASE.jar**:包含Spring Bean的定义和管理,包括bean的创建、初始化、配置和销毁。它是Spring容器的核心,负责读取配置文件并管理bean的生命周期。 7. **spring-test-4.1.5.RELEASE.jar...
它是Spring IoC容器的基础,负责实例化、定位、配置应用程序中的对象。 - **ApplicationContext**:扩展了BeanFactory的功能,提供了对国际化支持、事件发布、资源访问等服务。它是面向整个应用的IoC容器。 - **Web ...
10. **Chapter 17** - Spring Boot:简述Spring Boot快速开发框架,如何简化Spring应用的初始化和配置。包括自动配置、起步依赖和命令行界面等内容。 这些章节覆盖了Java EE开发中的关键技术和最佳实践,从基础到...
Spring IoC 容器通过 XML 配置文件或注解方式实现对象的初始化和依赖注入。开发者可以定义bean的配置,如类名、属性值等,并声明bean之间的依赖关系。容器根据这些配置信息创建并管理bean,自动完成对象的实例化和...
- **Web应用**:在Spring MVC中,Controller层的bean通过IoC容器管理,方便进行依赖注入和AOP增强。 总之,Spring IoC容器作为核心组件,极大地提高了软件设计的灵活性和可维护性,通过解耦和管理对象的生命周期,...
1. **web.xml**:配置DispatcherServlet,包括初始化参数、拦截器、监听器等。 2. **spring-mvc.xml**:定义Bean、数据源、事务管理器、视图解析器、HandlerMapping和HandlerAdapter等。 四、Spring MVC 原理 1. *...
在这个案例实践中,你将会看到如何配置这三个框架,从初始化Spring上下文,到设置Spring MVC的DispatcherServlet,再到配置Hibernate的数据源和实体映射。你将学习到如何在Spring中声明和使用Service层,这些Service...