Spring源码解析(8)——ApplicationContext

回顾上篇

上篇文章《属性注入》,我们已经分析完了bean中的属性是如何注入进去的。到目前为止我们已经分析完了Spring创建一个bean的全流程。先是解析配置的xml文件,将xml文件里配置的信息解析成BeanDefinition,然后通过BeanDefinition来创建bean,同时也会将bean的属性值注入。这里面也涉及到一个循环依赖的问题,也分析了一下Spring是如何来解决循环依赖的。上面的分析我们都是基于BeanFacotry接口的实现类XmlBeanFactory来分析的,在Spring中还提供了另外一个接口ApplicationContext,这个接口包含了BeanFacotry的所有功能,也提供了更多的扩展功能。接下来我们就看看ApplicationContext。

分析源码实现

ApplicationContext的使用

package com.guiji.test;

import com.guiji.bean.MyTestBean;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanFactoryTest {
   

	@Test
	public void testSimpleLoad(){
   

		//BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("BeanFactoryTest.xml"));
		
		ApplicationContext beanFactory = new ClassPathXmlApplicationContext("BeanFactoryTest.xml");
		
		MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");

		String testStr = myTestBean.getTestStr();

		System.out.println(testStr);

		Assert.assertEquals("javaGuiji",testStr);
		
	}

}

进入到ClassPathXmlApplicationContext中,开始对ClassPathXmlApplicationContext进行分析。

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
   
	this(new String[] {
   configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
   

	super(parent);
	//设置xml文件路径
	setConfigLocations(configLocations);
	if (refresh) {
   
		refresh();
	}
}

这里面首先设置了xml文件的路径,然后在调用了refresh方法。ApplicationContext 的功能几乎都是在refresh方法里面完成的。我们看到refresh方法。

@Override
public void refresh() throws BeansException, IllegalStateException {
   
	synchronized (this.startupShutdownMonitor) {
   
		// 准备刷新的上下文环境
		prepareRefresh();
		// 创建beanFactory,读取xml文件,解析xml文件,注册BeanDefinition
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		// 添加扩展功能,比如添加SPEL语言支持、属性编辑器支持,
		prepareBeanFactory(beanFactory);
		try {
   
			// 空方法 允许子类进行扩展
			postProcessBeanFactory(beanFactory);
			// 激活BeanFactory处理器
			invokeBeanFactoryPostProcessors(beanFactory);
			// 注册BeanPostProcessors
			registerBeanPostProcessors(beanFactory);
			// 初始化消息源,国际化处理
			initMessageSource();
			// 初始化广播器,用于广播事件
			initApplicationEventMulticaster();
			// 空方法,留给子类实现
			onRefresh();
			// 注册监听器
			registerListeners();
			// 初始化剩下的单实例
			finishBeanFactoryInitialization(beanFactory);
			// 完成刷新过程,通知生命周期处理器,发布ContextRefreshedEvent事件
			finishRefresh();
		}
		catch (BeansException ex) {
   
			if (logger.isWarnEnabled()) {
   
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}
			//发生异常 销毁创建的bean
			destroyBeans();
			cancelRefresh(ex);
			throw ex;
		}
		finally {
   
			resetCommonCaches();
		}
	}
}

这段代码逻辑很清晰,每一块内容都封装到一个方法里面,下面我们重点分析obtainFreshBeanFactoryinvokeBeanFactoryPostProcessorsregisterBeanPostProcessorsinitApplicationEventMulticasterregisterListenersfinishBeanFactoryInitializationfinishRefresh这几个方法。

obtainFreshBeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   
	refreshBeanFactory();
	return getBeanFactory();
}
	
@Override
protected final void refreshBeanFactory() throws BeansException {
   
	if (hasBeanFactory()) {
   
		destroyBeans();
		closeBeanFactory();
	}
	try {
   
		//创建beanFactory
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		customizeBeanFactory(beanFactory);
		//读取xml文件,解析xml文件,注册BeanDefinition
		loadBeanDefinitions(beanFactory);
		this.beanFactory = beanFactory;
	}
	catch (IOException

你可能感兴趣的:(Spring源码解析,spring,java)