spring源码学习(二)

这一段我主要去看看spring容器的创建,继续(一)的代码,我们看

if (this.context == null) {
				this.context = createWebApplicationContext(servletContext);
			}

创建容器

protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
		Class<?> contextClass = determineContextClass(sc);
		if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
			throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
					"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
		}
		ConfigurableWebApplicationContext wac =
				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
		return wac;
	}
Class<?> contextClass = determineContextClass(sc);

既然要创建一个context,首先需要确定context是由什么类定义, 这一行就是获取context的类,我们点进去看

protected Class<?> determineContextClass(ServletContext servletContext) {
		String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
		if (contextClassName != null) {
			try {
				return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
			}
			catch (ClassNotFoundException ex) {
				throw new ApplicationContextException(
						"Failed to load custom context class [" + contextClassName + "]", ex);
			}
		}
		else {
			contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
			try {
				return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
			}
			catch (ClassNotFoundException ex) {
				throw new ApplicationContextException(
						"Failed to load default context class [" + contextClassName + "]", ex);
			}
		}
	}
servletContext.getInitParameter

 是取web.xml里的配置参数,意思就是先看看我们有没有自己定义context的类

return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());

 如果我们定义了,直接返回这个class.

contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());

如果没有定义的话,去defaultStrategies里去取,WebApplicationContext的类名作为key

那么defaultStrategies里的值哪来的呢,我们ctrl+o,然后搜索defaultStrategies,会看到

private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
private static final Properties defaultStrategies;

	static {
		// Load default strategy implementations from properties file.
		// This is currently strictly internal and not meant to be customized
		// by application developers.
		try {
			ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
			defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
		}
		catch (IOException ex) {
			throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
		}
	}

 在类加载的时候,会去当前目录取这个属性文件

ContextLoader.properties

我们看看spring的jar包中,当前这个类是org.springframework.web.context.ContextLoader,那么我们就去web包的context路径下看



 

可以看到contextLoader.properties文件在这里,打开查看里面的配置,我们会发现spring在web工程中,默认使用的context,默认是xmlWebApplicationContext


看到这里我会建议最好先去看看xmlWebApplicationContext的上下继承关系,至少需要知道它具备哪些特性

有了大致的了解后再接着往下读

接着回到创建容器的代码里来

protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
		Class<?> contextClass = determineContextClass(sc);
		if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
			throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
					"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
		}
		ConfigurableWebApplicationContext wac =
				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
		return wac;
	}

第一行我们知道了spring的web工程会首先取用户在web.xml里配置的context的类,如果用户配置了,就采用配置的,如果用户没有配置,就采用默认的xmlWebApplicationContext

接着进入第2行,不管采用配置的还是默认的,spring要求,必须是可配置的,也就是configurable.

只有是Configurable,才能进行后续的配置操作,至于Configurable的具体含义,我们后面会了解到。

现在紧接着

ConfigurableWebApplicationContext wac =
				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

这个方法是用xmlWebApplicationContext的类作为参数,调用它的无参构造,实例一个对象,也就是我们期待已久的spring容器对象,至此,spring容器创建了

接下来在(三)里,我们去学习填充容器的过程,包括它是怎么配置的,还有最重要的,它是怎么刷新的,“刷新”这个动作就是将spring的xml配置变成bean,这个是ioc的核心,会涉及到一系列  beans包和core包,还有io包下的东西,所以建议一起学习的朋友在看下去之前,先随便了解一些bean包的相关结构和知识。
 

猜你喜欢

转载自rkdu2-163-com.iteye.com/blog/2003531