spring源码之旅(2)_applicationcontext启动流程分析
一、 一个简单的应用
此次分析从spring的一个入门级的应用作为入口,下面是应用的代码:
TestAction类(TestAction.java)
package xqq.ioc.listen1; public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext(“xqq//ioc//listen1//listen1_beans.xml”); Action myAction=(Action)ctx.getBean(“myAction”); System.out.println(myAction.execute(“Qiang Qiang”)); } |
Action接口代码:(Action.java)
package xqq.ioc.listen1; public interface Action { String execute(String str); } |
UpperAction类代码:(UpperAction.java)
package xqq.ioc.listen1; public class UpperAction implements Action { String message; public String execute(String str) { // TODO Auto-generated method stub return (getMessage()+str).toUpperCase(); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } |
Spring配置文件(listen1_beans.xml):
<?xml version=“1.0” encoding=“UTF-8”?> <beans xmlns=“http://www.springframework.org/schema/beans” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd”> <bean id=“myAction” class=“xqq.ioc.listen1.UpperAction”> <property name=“message”> <value>Hello</value> </property> </bean> </beans> |
二、 构造方法跟踪
1. 程序进入main方法后,第一步就是通过加载一个spring xml配置文件的路径创建applicationContext
ApplicationContext ctx=new ClassPathXmlApplicationContext(“xqq//ioc//listen1//listen1_beans.xml”); |
2. 进入ClassPathXmlApplicationContext的构造方法中
public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); } |
3. 由上面的代码可以看见,代码进入了一个重载的构造方法
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); this.configLocations = StringUtils.trimArrayElements(configLocations); if (refresh) { refresh(); } } |
4. 由上面代码可见首先调用超类的构造方法,经过代码跟踪,超类构造方法的调用直至AbstractApplicationContext类的构造方法止
public AbstractApplicationContext(ApplicationContext parent) { this.parent = parent; this.resourcePatternResolver = getResourcePatternResolver(); } |
在AbstractApplicationContext构造方法中设置了parent,并且设置了resourcePatternResolver属性,查看getResourcePatternResolver()方法的源码:
protected ResourcePatternResolver getResourcePatternResolver() { return new PathMatchingResourcePatternResolver(this); } |
由上面可见在AbstractApplicationContext类中默认创建了一个PathMatchingResourcePatternResolver对象来进行资源路径的解析
三、 refresh()方法刷新流程
在3中调用完超类的构造方法后,最重要的就是调用refresh()方法了,refresh()方法内部实现了整个applicationContext的启动流程
Refresh()方法是在AbstractApplicationContext类内部实现的,在3中调用的其实是超类的refresh()方法
/** * 刷新,spring ApplicationContext初始化并工作的核心方法 */ public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //准备刷新,设置启动时间和active属性的值 prepareRefresh(); //在此方法内部调用抽象方法refreshBeanFactory(),并返回刷新后的beanFactory实例 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //设置beanFactory的标准特性,包括类加载器,ResourceEditorRegistrar,为beanFactory增加ApplicationContextAwareProcessor的beanPost后置处理器,并调用ignoreDependencyInterface()方法设置自动装配时被忽略的类型 prepareBeanFactory(beanFactory); try { //模板方法,供子类进行覆盖实现,本类默认实现为空 postProcessBeanFactory(beanFactory); //调用本类中的BeanFactoryPostProcessor集合和beanFactory中的所有后置处理器对beanFactory进行处理,如果beanFactory中的后置处理器有顺序,则按照顺序进行处理 invokeBeanFactoryPostProcessors(beanFactory); //按顺序将beanFactory中的bean后置处理器全都加入至beanFactory的bean后置处理器列表中 registerBeanPostProcessors(beanFactory); //初始化message source,并设置其父message source initMessageSource(); //初始化ApplicationEvent消息广播器 initApplicationEventMulticaster(); //模板方法,供子类进行覆盖实现,本类默认实现为空 onRefresh(); //将本类的ApplicationListener和配置beans中的ApplicationListener添加至本类的消息广播器上 registerListeners(); //beanFactory实例化非延迟的单例bean beanFactory.preInstantiateSingletons(); //完成刷新,并发布ContextRefreshedEvent事件 finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. beanFactory.destroySingletons(); // Reset ‘active’ flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } } |
通过阅读refresh()方法代码,可以非常清楚的了解spring applicationcontext启动时的整个初始化流程:
准备刷新(记录启动时间,设置active属性为true)——-à获取刷新后的beanFactory——-à
设置beanFacotry类加载器、默认属性编辑器、默认beanPost后置处理器——-à获取beanFactory中的BeanFactoryPostProcessor类型的对象,并让其对beanFactory进行后置处理——-à将配置中的beanPostProcessor类型的对象加入至beanFactory中——-à初始化messageSource(如有配置,则获取配置文件中的messageSource bean对象,如没有,则创建DelegatingMessageSource让其将对messageSource的请求代理给父容器的messageSource对象处理) ——-à初始化ApplicationEvent事件广播器(如有配置,则使用配置文件中所配置的消息广播器,否则默认使用SimpleApplicationEventMulticaster作为消息广播器) ——-à调用模板方法onRefresh()——-à注册配置文件中所配置的消息监听器—–àbeanFactory实例化非延迟的单例bean—–à完成刷新,并发布ContextRefreshedEvent事件
四、 ApplicationContext内部beanFactory的创建
整个刷新过程中,创建了新的beanFactory,原有的旧beanFactory将被丢弃,obtainFreshBeanFactory()方法内部调用的refreshBeanFactory()方法实现了这种功能。refreshBeanFactory()具体由子类AbstractRefreshableApplicationContext进行实现,先将旧的beanFactory中的所有单例全都销毁,然后创建一个新的beanFactory,加载beanDefinitions,并将新的beanFactory赋给本类的beanFactory实例。
ConfigurableListableBeanFactory oldBeanFactory = null; synchronized (this.beanFactoryMonitor) { oldBeanFactory = this.beanFactory; } if (oldBeanFactory != null) { //销毁bean工厂中的所有单例 oldBeanFactory.destroySingletons(); synchronized (this.beanFactoryMonitor) { this.beanFactory = null; } }
// Initialize fresh bean factory. try { //创建新的beanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); //模板方法,供子类覆盖实现,为beanFactory提供客户端自定义的操作 customizeBeanFactory(beanFactory); //从beanFactory中加载bean定义 loadBeanDefinitions(beanFactory); //将创建的beanFactory设置为本类的beanFactory实例 synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } }………… |
在AbstractRefreshableApplicationContext类的createBeanFactory()方法中实现了为ApplicationContext创建内部beanFactory的功能,此内部beanFactory保存了根据配置文件解析而来的各个bean的BeanDefinition实例,因此ApplicationContext创建、查找bean以及对bean进行操作等功能的实现都是通过其内部beanFactory实现的。下面是此方法的代码:
protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); } |
由以上代码可以看见,以applicationcontext父亲的内部beanFactory作为构造参数,创建了DefaultListableBeanFactory对象作为applicationcontext的内部beanFactory。