【Spring源码解析】之IOC容器在Web容器中的启动

在【Spring源码解析】之IOC容器这一篇中我们学习了IOC容器本身的实现。下面我们看看在典型的Web容器中,Spring的IOC容器是怎么被载入和起作用的。简单的说,在Web容器中,通过ServletContext为Spring的IOC容器提供宿主环境。

下面看一下Web环境下,Web.xml文件中 spring的配置;

<!-- 配置Spring的监听器,用于初始化ApplicationContext对象 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext*.xml</param-value>
	</context-param>
在Web容器中启动Spring应用程序就是一个建立上下文体系的过程。我们通过Spring的监听器配置来跟踪下代码ContextLoaderListener:

public class ContextLoaderListener implements ServletContextListener {

	private ContextLoader contextLoader;

	/**
	 * 初始化 根 web 应用的上下文
	 */
	public void contextInitialized(ServletContextEvent event) {
		this.contextLoader = createContextLoader();
		this.contextLoader.initWebApplicationContext(event.getServletContext());
	}

	/**
	 * Create the ContextLoader to use. Can be overridden in subclasses.
	 * @return the new ContextLoader
	 */
	protected ContextLoader createContextLoader() {
		return new ContextLoader();
	}

	/**
	 * Return the ContextLoader used by this listener.
	 * @return the current ContextLoader
	 */
	public ContextLoader getContextLoader() {
		return this.contextLoader;
	}

	/**
	 * Close the root web application context.
	 */
	public void contextDestroyed(ServletContextEvent event) {
		if (this.contextLoader != null) {
			this.contextLoader.closeWebApplicationContext(event.getServletContext());
		}
	}
}
在ContextLoaderListener这个类中我们找到它初始化Initialize the root web application context.这个方法中调用的【initWebApplicationContext】方法。点进去之后我们看到它返回是这个WebApplicationContext【web应用上下文对象】。我们在WebApplicationContext这个接口中看下它的原生态的代码:

public interface WebApplicationContext extends ApplicationContext {

	/**
	 * 这里定义的常量用于在ServletContext中存取根上下文
	 */
	String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";


	/**
	 * Scope identifier for request scope: "request".
	 * Supported in addition to the standard scopes "singleton" and "prototype".
	 */
	String SCOPE_REQUEST = "request";

	/**
	 * Scope identifier for session scope: "session".
	 * Supported in addition to the standard scopes "singleton" and "prototype".
	 */
	String SCOPE_SESSION = "session";

	/**
	 * Scope identifier for global session scope: "globalSession".
	 * Supported in addition to the standard scopes "singleton" and "prototype".
	 */
	String SCOPE_GLOBAL_SESSION = "globalSession";


	/**
	 * 对于WebApplicationContext来说需要得到Web的ServletContext
	 */
	ServletContext getServletContext();
	
}
上面的代码段是spring为Web应用程序提供的上下文接口。在一般的启动过程中,spring会使用一个默认的实现XmlWebApplicationContext【它实现了接口WebApplicationContext】。这个实现作为一个根上下文容器,在Web容器中被建立起来。具体的过程我们将分析一下。下面有请这个XmlWebApplicationContext实现出场。
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {

	/** 这儿是root上下文定义信息的默认存放位置 */
	public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
	public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
	public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";


	/**
	 * 加载bean定义信息
	 */
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		//这里解释一下,XMLApplicationContext,当然使用XmlBeanDefinitionReader来对bean定义信息来进行解析
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}

	/**
	 * 保留,不解释
	 */
	protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
	}

	/**
	 *使用XmlBeanDefinitionReader来读入bean定义信息
	 */
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			for (int i = 0; i < configLocations.length; i++) {
				reader.loadBeanDefinitions(configLocations[i]);
			}
		}
	}

	/**
	 * 取得bean定义的位置信息,默认的路径是 /WEB-INF/applicationContext.xml
	 */
	protected String[] getDefaultConfigLocations() {
		if (getNamespace() != null) {
			return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
		}
		else {
			return new String[] {DEFAULT_CONFIG_LOCATION};
		}
	}
}
对于一个 Spring 激活的web 应用程序,可以通过使用Spring 代码声明式的指定在web 应用程序启动时载入应用程序上下文。











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值