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 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();
}
}
}