基本概念

Spring Ioc 容器被创建之后,接下来就是它的初始化过程了。该过程包含了配置、刷新两个步骤 

刷新由 Spring 容器自己实现,具体发生在 ConfigurableApplicationContext 的 refresh 方法中。

首先来看该接口的继承关系:

由于这里 Spring 的配置文件采用 xml 形式,所以 Ioc 容器的类型默认为 XmlWebApplicationContext。接下来就以该类的 refresh 方法为入口,探究下 Ioc 容器的刷新过程。


原理分析

该类的 refresh 方法继承自己父类 AbstractApplicationContext,观察代码可以发现该方法包含了众多方法,这里只探究下 1、2 过程。

private final Object startupShutdownMonitor = new Object();

public void refresh() throws BeansException, IllegalStateException {
// 加锁
synchronized (this.startupShutdownMonitor) {
// 1.准备刷新
prepareRefresh(); // 2.创建内部容器,该容器负责 Bean 的创建与管理
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try {
postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) {
// 省略代码... destroyBeans(); cancelRefresh(ex); throw ex; } finally {
resetCommonCaches();
}
}
}

准备刷新

初始化准备,即为 Ioc 容器的初始化过程做准备,该过程与 Spring 的 Environment 有关,这里暂不探究。

// 容器早期发布事件集
private Set<ApplicationEvent> earlyApplicationEvents; protected void prepareRefresh() {
// 省略部分代码... // 1.激活容器
this.active.set(true); // 2.初始化 Environment 的 propertySources 属性
initPropertySources(); // 3.校验 Environment 的 requiredProperties 是否都存在
getEnvironment().validateRequiredProperties(); // 4.创建事件集合
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

来看下 initPropertySources 这个方法, 它与 Spring 容器的 Environment 有关:

protected void initPropertySources() {
// 取得配置过程中创建的容器环境
ConfigurableEnvironment env = getEnvironment(); // 初始化 Environment 的 propertySources 属性
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).
initPropertySources(this.servletContext, this.servletConfig);
}
}

创建内部容器

之前介绍过 ApplicationContext 对象里面会包含了一个 BeanFactory 对象。有关 Bean 的基本功能是调用内部的 BeanFactory 对象来实现的。

在这里, BeanFactory 具体指的是 ConfigurableListableBeanFactory ,来看它们的继承关系:


下面来看 obtainFreshBeanFactory 的具体实现:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

    // 1.刷新 BeanFactory
refreshBeanFactory(); // 2.取得 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 省略部分代码... return beanFactory;
}

1.刷新 BeanFactory

下面来看刷新内部 BeanFactory 的实现过程:

protected final void refreshBeanFactory() throws BeansException {

    // 1.判断是否存在 Beanfactory ,存在则销毁并关闭它
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
} try {
// 2.创建 BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory(); // 3.设置 BeanFactory 的 id,同它外部的 Spring 容器一致
beanFactory.setSerializationId(getId()); // 4.定制 BeanFactory 初始化,暂不探究
customizeBeanFactory(beanFactory); // 5.加载 Bean 实例
loadBeanDefinitions(beanFactory); // 6.将 BeanFactory 设置为 Spring 容器的内部 BeanFactory
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
} }catch (IOException ex) {
// 抛出异常...
}
}

①判断是否存在 BeanFactory,存在则销毁、关闭容器的内部 BeanFactory

// 1.判断是否存在存在内部 BeanFactory
protected final boolean hasBeanFactory() {
synchronized (this.beanFactoryMonitor) {
return (this.beanFactory != null);
}
} // 2.若存在销毁内部 BeanFactory 的所有 Bean
protected void destroyBeans() {
getBeanFactory().destroySingletons();
} // 2.关闭 内部 BeanFactory
protected final void closeBeanFactory() {
synchronized (this.beanFactoryMonitor) {
this.beanFactory.setSerializationId(null);
this.beanFactory = null;
}
}

②创建 BeanFactory,这里会默认创建 DefaultListableBeanFactory 类作为内部容器(内部 BeanFactory)。

protected DefaultListableBeanFactory createBeanFactory() {
// 1.取得内部 BeanFactory 的父容器
// 2.创建内部 BeanFactory
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
} protected BeanFactory getInternalParentBeanFactory() {
// 判断取得 Spring 容器的父容器类型
// 匹配,则返回父容器内部 BeanFactory,否则返回父容器
return (getParent() instanceof ConfigurableApplicationContext) ?
((ConfigurableApplicationContext) getParent()).getBeanFactory() :getParent();
} public DefaultListableBeanFactory(BeanFactory parentBeanFactory) {
super(parentBeanFactory);
}
public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) {
this();
setParentBeanFactory(parentBeanFactory);
}


③加载 Bean 实例,该过程由 BeanDefinitionReader 负责,下篇在详细分析。


2.取得 BeanFactory

// 取得 BeanFactory
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
// 抛出异常...
}
return this.beanFactory;
}
}

总结

下面通过流程图来总结下 Spring Ioc 容器的初始化过程:

最新文章

  1. Asp.net Core 通过 Ef Core 访问、管理Mysql
  2. Windows下快速安装Flask的一次经历
  3. CRM基于.NET的增删改查
  4. SQL Server 2008 R2——软件创建月表时同时创建一个触发器
  5. 【2016-09-16】UbuntuServer14.04或更高版本安装问题记录
  6. 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)
  7. C# 使用 Abot 实现 爬虫 抓取网页信息 源码下载
  8. jsmooth 中文乱码
  9. MapReduce编程系列 — 6:多表关联
  10. Mvc Model 模板的获取【学习笔记】
  11. Android -------- 网络访问数据
  12. Oracle11g R2学习系列 之九 PL/SQL语言
  13. JBoss + EJB3 + MySql : 开发第一个EJB
  14. springframwork历史版本下载地址
  15. Spring装配Bean之组件扫描和自动装配
  16. android studio 编辑markdown文件
  17. Windows 7安装Tensorflow
  18. spring ioc beanfactory 关系图
  19. JAVA设计模式详解(四)----------单例模式
  20. 【题解】 bzoj4033: [HAOI2015]树上染色* (动态规划)

热门文章

  1. BZOJ1218:[HNOI2003]激光炸弹
  2. java中toString() 、(String)、String.valueOf的区别
  3. AI:AI
  4. 《Kubernetes权威指南第2版》学习(三)RC学习
  5. MY_SQLCode
  6. MongoDB一些基本的命令
  7. Java探索之旅(8)——继承与多态
  8. 关于startservice的几个启动返回值的意义
  9. 文件格式——gff格式
  10. Spring JdbcTemplate+JdbcDaoSupport实例(和比较)