IOC的初始化过程(五)

1.概述

简单来说IOC容器的初始化过程是通过refresh()方法来启动的,这个方法表示IOC容器的正式启动。具体来说这个启动主要包含BeanDefinition的Resource定位、载入和注册三个过程。

2.IOC启动流程说明
  • 第一个过程是Resource定位过程。 这个 Resource定位指的是BeanDefinition的资源定位(例如我们平时Spring项目中配置的各种xml配置统一抽象为Resource资源),它由ResourceLoader通过统一的Resource接口来完成,这个Resource对这种形式的BeanDefinition的使用提供了统一接口。
  • 第二个过程是BeanDefinition的载入过程。 载入过程是把用户定义好的Bean表示成IOC容器内部的数据结构即BeanDefinition。BeanDefinition实际上就是POJO对象在IOC容器中的抽象,通过对BeanDefinition定义的数据结构,使IOC容器能够方便的对POJO对象也就是Bean对象进行管理。
  • 第三个过程就是BeanDefinition的向IOC的注册过程。 这个过程主要是通过BeanDefinitionRegistry接口完成实现的。注册过程是把载入过程中解析得到的BeanDefinition向IOC容器进行注册。其实IOC内部就是将解析得到的BeanDefinition注入到一个HashMap中去,IOC容器就是通过这个HashMap持有这些BeanDefinition数据的。
3.源代码解析

FileSystemXmlApplicationContext为例,核心继承关系为:

FileSystemXmlApplicationContext核心继承关系

示例代码为:
FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:bean.xml")

当我们执行上面这行代码的时候一个IOC的资源定位、解析、注册过程就被完成,下面我们就分析一下上述代码的核心执行流程。

/**
	 * Create a new FileSystemXmlApplicationContext, loading the definitions
	 * from the given XML file and automatically refreshing the context.
	 * @param configLocation file path
	 * @throws BeansException if context creation failed
	 */
	public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
		this(new String[] {configLocation}, true, null);
	}

我们选用的构造器为传入一个资源文件路径,实际调用的内部构造器为:

/**
	 * Create a new FileSystemXmlApplicationContext with the given parent,
	 * loading the definitions from the given XML files.
	 * @param configLocations array of file paths
	 * @param refresh whether to automatically refresh the context,
	 * loading all bean definitions and creating all singletons.
	 * Alternatively, call refresh manually after further configuring the context.
	 * @param parent the parent context
	 * @throws BeansException if context creation failed
	 * @see #refresh()
	 */
	public FileSystemXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		// 父容器设置
		super(parent);
		// 设置资源访问路径
		setConfigLocations(configLocations);
		// 刷新启动容器
		if (refresh) {
			refresh();
		}
	}

当我们执行refresh()方法的时候,我们的ApplicationContext高级上下文容器就已经创建好了,我们进入refresh()方法区查看具体执行的逻辑:

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// 刷新启动前的准备工作
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		// 获取Beanfatory->资源的定位和解析就是在此方法中执行的
		//(1)AbstractApplicationContext#obtainFreshBeanFactory()
		//(2)AbstractApplicationContext#refreshBeanFactory()实际执行子类
		//(3)AbstractRefreshableApplicationContext#refreshBeanFactory()的方法
		创建DefaultListableBeanFactory并loadBeanDefinitions`
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// 配置BeanFactory标准Context特征,比如 classloader,后置处理等。
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			// 允许添加BeanFactoryProcessor来修改beanFactory,子类覆盖方法做额外处理  
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			// 回调 上面收集到的所有的 BeanFactoryProcessor 了
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			// 注册bean的处理器
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			// 国际化相关的初始化
			initMessageSource();

			// Initialize event multicaster for this context.
			// 初始化应用事件的广播
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// 留给子类Context实现一些特殊处理的模板方法(模板方法留给子类实现)
			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) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// Destroy already created singletons to avoid dangling resources.
			destroyBeans();

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

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			// 清理那些不需要的缓存数据
			resetCommonCaches();
		}
	}
}

微信公众号

发布了41 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Yunwei_Zheng/article/details/105680488
今日推荐