ApplicationContext加载xml

使用BeanFactory方式加载XML

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanTest.xml"));

使用ApplicationContext方式加载XML

ApplicationContext context = new ClassPathXmlApplicationContext("beanTest.xml");

ApplicationContext和BeanFactory两者都是用于加载bean的,但是相比之下,ApplicationContext提供了更多的功能扩展。

以ClassPathXmlApplicationContext作为切入点,开始对整体功能进行分析。

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

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

ClassPathXmlApplicationContext中可以将配置文件路径以数组的方式传入,ClassPathXmlApplicationContext可以对数组进行解析并进行加载。而对于解析及功能实现都在refresh()中实现。

public void setConfigLocations(String[] locations) {
		if (locations != null) {
			Assert.noNullElements(locations, "Config locations must not be null");
			this.configLocations = new String[locations.length];
			for (int i = 0; i < locations.length; i++) {
				this.configLocations[i] = resolvePath(locations[i]).trim();
			}
		}
		else {
			this.configLocations = null;
		}
	}

此函数主要用于解析给定的路径数组,如果数组中包含特殊符号,如${var},那么resolvePath中会搜寻匹配系统变量并替换。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}

refresh函数中包含了几乎ApplicationContext中提供的全部功能,而且逻辑非常清晰明了。

(1)初始化前的准备工作,例如对系统属性或者环境变量进行准备验证。

(2)初始化BeanFactory,并进行XML文件读取。

(3)对BeanFactory进行各种功能填充。

(4)子类覆盖方法做额外处理。

(5)激活各种BeanFactory处理器。

(6)注册拦截bean创建的bean处理器,这里只是注册,真正的调用是在getBean时候。

(7)为上下文初始化Message源,即对不同语言的消息体进行国际化处理。

(8)初始化应用消息广播器,并放入applicationEventMulticaster中。

(9)留给子类来初始化其他的bean。

(10)在所有注册的bean中查找listener bean,注册到消息广播中。

(11)初始化剩下的单实例(非惰性)。

(12)完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人。


猜你喜欢

转载自blog.csdn.net/panzm_csdn/article/details/80190792