一、             
						
				
				
						概述
						
								
								
								
						
				
		
		
				
						
								二、             
						
				
				
						Spring
				
				
						初始化之旅
						
								
								
						
				
		
		
				
						a)         
				
				Spring
				初始化的时候首先要运行的类为:
				org.springframework.web.context. ContextLoaderListener
				或
				org.springframework.web.context. ContextLoaderServlet
				。
		
		
				
						       
				
				它们在初始化函数里无一例外地实例化了
				ContextLoader
				类
				,
				然后调用了它的函数
				
						     public WebApplicationContext initWebApplicationContext(ServletContext )
				。
		
		
				
						       
				
				接下来看一下在这个方法里干了写什么
		
		
				
						b)        
				
				在他的方法体内,关键是“
				this.context = createWebApplicationContext(servletContext, parent);
				”新建了一个“
				ConfigurableWebApplicationContext
				”类型的对象,在这一步实例化中几乎完成了所有的
				spring
				初始化工作。读取了所有的
				spring
				配置文件。它的工作步骤如下所述。
		
		
				
						c)        
				
				首先,在将“
				ConfigurableWebApplicationContext
				”类型的对象实例化以后(这个对象实际的类型是这个包内的
				XmlWebApplicationContext
				),然后又给这个实例设置了三个属性,“
				wac.setParent(parent);
				”在默认的初始化过程中这一步设置了一个
				null
				值,然后又设置了一个“
				wac.setServletContext(servletContext);
				”,将系统默认的上下文设置进来,比较重要的是下面这一段:
				
						           
				
		
		
				
						       if (configLocation != null) {
		
		
				
						       //
				读取
				spring
				的应用配置文件
		
		
				
						       wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,Configurabl       eWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
		
		
				
						       }
		
		
				
						       
				
				它将我们的配置文件名放置到
				wac
				变量中,以待在后续的操作中使用。然后调用
				
						          
				
				“
				wac.refresh();
				”完成主要的初始化
				BeanFactory
				的操作。如下。
		
		
				
						d)        
				
				首先我们应该看一下我们实例化的对象
		
		
				
						       org.springframework.web.context.support.XmlWebApplicationContext
				的类图:
		
		
				
						 
				
		
		
				
						 
				
		
		
				
						e)         
				
				“
				wac.refresh();
				”从类结构里我们能找到这个方法来自它的父类:
				AbstractApplicationContext
				在它的
				refresh()
				方法内我们可以看到
				spring
				的复杂逻辑。
		
		
				
						       
				
				首先执行了
				refreshBeanFactory();
				(来自
				AbstractRefreshableApplicationContext
				)见
				 f),
		
		
				
						f)         
				
				refreshBeanFactory();
				这个方法由负责维护变量
				beanFactory
				的子类
				AbstractRefreshableApplicationContext
				实现,默认情况下这个方法直接实例化一个新的
				DefaultListableBeanFactory
				类型的
				BeanFacorty,
				然后调用一个起缓冲作用的配置函数生成一个将
				beanFacroty
				包装起来的对象
				beanDefinitionReader
				,然后对这个对象进行属性配置,实际上该方法主要负责生成一个临时的操作对象,对应调用的函数为“
				loadBeanDefinitions(beanFactory);
				”该方法为初始化期间较为重要的一个。
				
						       
				
				该方法来自其子类:
				AbstractRefreshableWebApplicationContext
				对应的函数:
		
		
				protected void loadBeanDefinitions(DefaultListableBeanFactory)
				,然后这里又调用了自己定义的
				protected void loadBeanDefinitions(XmlBeanDefinitionReader)
				方法。此时,它就使用到了在
				c)
				中设置了的(
				wac.setConfigLocations(……))
				我们开发中密切相关的配置文件。(同时也要记住此时这个函数的参数
				beanDefinitionReader
				,之前已经设置了“
				
						beanDefinitionReader.setResourceLoader(this);
				
				”这里的
				this
				是我们在前面见到的
				
						XmlWebApplicationContext
				
				(一个定义好了的上下文))。接着往下:
		
		
				
						       
				
				“
				reader.loadBeanDefinitions(configLocations[i]);
				”
				reader
				开始加载我们配置文件内的东西了,不过真正复杂的实现此时才开始,我们继续往下走,在接下来的方法内默认情况下会执行:
		
		
				if (resourceLoader instanceof ResourcePatternResolver) 
				(该判断条件为
				true
				)
				,
				由于从上面我们知道:
				
						beanDefinitionReader.setResourceLoader(this);
				
				而
				this
				的类型为:
				
						XmlWebApplicationContext
				
				所以
				
						((ResourcePatternResolver) resourceLoader).getResources(location);
				
				得到一个
				Resource[]
				数组,接下来调用:
		
		
				
						int loadCount = loadBeanDefinitions(resources);
				
				该函数继续调用自己子类定义的一系列临时接口最终执行到
				
						return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
				
				在这个函数内初始化了处理
				xml
				文件的一些对象并将用户的配置文件解析为一个
				Document
				对象。然后又执行了一系列函数直到
		
		
				
						return parser.registerBeanDefinitions(this, doc, resource);
				
				这个函数来自我们新建的
				DefaultXmlBeanDefinitionParser
				,在这个类里最终执行了对
				xml
				文件的解析工作和对
				beanFacroty
				变量执行了设置工作。
		
		
				
						g)        
				
				终于我们从这些繁杂的逻辑中跳了出来,继续执行
				AbstractApplicationContext.refresh()
				下面的工作,后续的代码主要仍旧是往一些常量里面设值。
		
		此时
		spring
		初始化过程就结束了。