白话Spring源码(十三):Spring Context源码分析

本文介绍Spring框架中如何通过ApplicationContext整合IOC和AOP功能,实现对外提供统一的接口。详细解析了ClassPathXmlApplicationContext的refresh()方法,展示了如何加载配置文件、初始化BeanFactory、注册BeanPostProcessors以及实现AOP的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前几篇博客给大家介绍了Spring框架的IOC和AOP的源码,那怎么把这两个核心组件连接起来对外提供更好用的接口呢?这时context包里的ApplicationContext就登场了。

简单使用

我们先看个ApplicationContext使用的demo:

ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
Person person=(Person)context.getBean("person");
person.sayHello();

就是这么简单,ApplicationContext封装了IOC和AOP的两大核心功能,对外提交了简单的接口。

分析源码

我们先看ClassPathXmlApplicationContext的源码:

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {

	private String[] configLocations;


	public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
		this.configLocations = new String[] {configLocation};
		refresh();
	}


	public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
		this.configLocations = configLocations;
		refresh();
	}


	public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent)
			throws BeansException {
		super(parent);
		this.configLocations = configLocations;
		refresh();
	}

	protected String[] getConfigLocations() {
		return this.configLocations;
	}

}

这里关键代码都在refresh()里

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

其他代码

	public void refresh() throws BeansException {
		this.startupTime = System.currentTimeMillis();

		// 加载BeanFactory,子类去实现
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();

		beanFactory.registerCustomEditor(Resource.class, new ContextResourceEditor(this));
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyType(ResourceLoader.class);
		beanFactory.ignoreDependencyType(ApplicationContext.class);
		postProcessBeanFactory(beanFactory);

		// invoke factory processors registered with the context instance
		for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
			BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
			factoryProcessor.postProcessBeanFactory(beanFactory);
		}

		if (getBeanDefinitionCount() == 0) {
			logger.warn("No beans defined in ApplicationContext [" + getDisplayName() + "]");
		}
		else {
			logger.info(getBeanDefinitionCount() + " beans defined in ApplicationContext [" + getDisplayName() + "]");
		}

		// 执行BeanFactory的PostProcessors
		invokeBeanFactoryPostProcessors();

		// 注册bean的beanProcessors实现拦截器,AOP
		registerBeanPostProcessors();

		// 初始化MessageSource,支持国际化
		initMessageSource();

		// 调用子类里的自定义刷新代码
		onRefresh();

		// 加载所有监听器
		refreshListeners();

		// 预处理单例
		beanFactory.preInstantiateSingletons();

		// 调用上下文刷新事件
		publishEvent(new ContextRefreshedEvent(this));
	}

}

AbstractXmlApplicationContext里的refreshBeanFactory

	protected void refreshBeanFactory() throws BeansException {
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
			beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
			initBeanDefinitionReader(beanDefinitionReader);
			loadBeanDefinitions(beanDefinitionReader);
			this.beanFactory = beanFactory;
			if (logger.isInfoEnabled()) {
				logger.info("Bean factory for application context '" + getDisplayName() + "': " + beanFactory);
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing XML document for application context [" +
			                                      getDisplayName() + "]", ex);
		} 
	}

这里封装了IOC的核心实现代码,看过IOC源码的应该很容易看懂,可以看我前几篇关于IOC的博客!

我们在前面介绍AOP的博客里知道AOP主要是通过BeanPostProcessor接口实现的,在refresh()方法里调用了registerBeanPostProcessors()

	private void registerBeanPostProcessors() throws BeansException {
		String[] beanNames = getBeanDefinitionNames(BeanPostProcessor.class);
		if (beanNames.length > 0) {
			List beanProcessors = new ArrayList();
			for (int i = 0; i < beanNames.length; i++) {
				beanProcessors.add(getBean(beanNames[i]));
			}
			Collections.sort(beanProcessors, new OrderComparator());
			for (Iterator it = beanProcessors.iterator(); it.hasNext();) {
				getBeanFactory().addBeanPostProcessor((BeanPostProcessor) it.next());
			}
		}
	}

好了,现在我们知道context的主要作用是封装Spring的IOC和AOP两大核心功能,对外提供接口,其实这也类似设计模式里的门面模式!

下篇博客重点给大家介绍context的又一个核心功能:事件机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haoxin963

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值