/**
 * 重点在于构造方法理解
 * @param configLocation
 * @throws BeansException
 */

// configLocation 包含了 BeanDefinition 所在的文件路径
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
}

// 可以定义多个 BeanDefinition 所在的文件路径
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
    this(configLocations, true, null);
}

// 在定义多个 BeanDefinition 所在的文件路径 的同时,还能指定自己的双亲 IoC 容器
public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
    this(configLocations, true, parent);
}

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
    this(configLocations, refresh, null);
}

/**
 * 如果应用直接使用 FileSystemXmlApplicationContext 进行实例化,则都会进到这个构造方法中来
 */
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
        throws BeansException {

// 动态地确定用哪个加载器去加载我们的配置文件
    super(parent);
    // 告诉读取器 配置文件放在哪里,该方法继承于爷类 AbstractRefreshableConfigApplicationContext
    setConfigLocations(configLocations);
    if (refresh) {
        // 容器初始化
        refresh();
    }
}

/**
 * 实例化一个 FileSystemResource 并返回,以便后续对资源的 IO 操作
 * 本方法是在其父类 DefaultResourceLoader 的 getResource 方法中被调用的,
 */
@Override
protected Resource getResourceByPath(String path) {
    if (path != null && path.startsWith("/")) {
        path = path.substring(1);
    }
    return new FileSystemResource(path);
}

/**
 * 容器初始化的过程:BeanDefinition 的 Resource 定位、BeanDefinition 的载入、BeanDefinition 的注册。
 * BeanDefinition 的载入和 bean 的依赖注入是两个独立的过程,依赖注入一般发生在 应用第一次通过
 * getBean() 方法从容器获取 bean 时。
 *
 * 另外需要注意的是,IoC 容器有一个预实例化的配置(即,将 AbstractBeanDefinition 中的 lazyInit 属性
 * 设为 true),使用户可以对容器的初始化过程做一个微小的调控,lazyInit 设为 false 的 bean
 * 将在容器初始化时进行依赖注入,而不会等到 getBean() 方法调用时才进行
 */
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 调用容器准备刷新,获取容器的当前时间,同时给容器设置同步标识
        prepareRefresh();

// 告诉子类启动 refreshBeanFactory() 方法,BeanDefinition 资源文件的载入从子类的 refreshBeanFactory() 方法启动开始
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 为 BeanFactory 配置容器特性,例如类加载器、事件处理器等
        prepareBeanFactory(beanFactory);

try {
            // 为容器的某些子类指定特殊的 BeanPost 事件处理器
            postProcessBeanFactory(beanFactory);

// 调用所有注册的 BeanFactoryPostProcessor 的 Bean
            invokeBeanFactoryPostProcessors(beanFactory);

// 为 BeanFactory 注册 BeanPost 事件处理器.
            // BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件
            registerBeanPostProcessors(beanFactory);

// 初始化信息源,和国际化相关.
            initMessageSource();

// 初始化容器事件传播器
            initApplicationEventMulticaster();

// 调用子类的某些特殊 Bean 初始化方法
            onRefresh();

// 为事件传播器注册事件监听器.
            registerListeners();

// 初始化 Bean,并对 lazy-init 属性进行处理
            finishBeanFactoryInitialization(beanFactory);

// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
            finishRefresh();
        }

catch (BeansException ex) {
            // 销毁以创建的单态 Bean
            destroyBeans();

// 取消 refresh 操作,重置容器的同步标识.
            cancelRefresh(ex);

throw ex;
        }
    }
}

/**
 * 在这里完成了容器的初始化,并赋值给自己私有的 beanFactory 属性,为下一步调用做准备
 * 从父类 AbstractApplicationContext 继承的抽象方法,自己做了实现
 */
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 如果已经建立了 IoC 容器,则销毁并关闭容器
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 创建 IoC 容器,DefaultListableBeanFactory 类实现了 ConfigurableListableBeanFactory 接口
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        // 对 IoC 容器进行定制化,如设置启动参数,开启注解的自动装配等
        customizeBeanFactory(beanFactory);
        // 载入 BeanDefinition,在当前类中只定义了抽象的 loadBeanDefinitions() 方法,具体实现 调用子类容器
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            // 给自己的属性赋值
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

/*
 * 实现了基类 AbstractRefreshableApplicationContext 的抽象方法
 */
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口,在初始化 XmlBeanDefinitionReader 时
    // 将 BeanDefinition 注册器注入该 BeanDefinition 读取器
    // 创建用于从 Xml 中读取 BeanDefinition 的读取器,并通过回调设置到 IoC 容器中去,容器使用该读取器读取 BeanDefinition 资源
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

beanDefinitionReader.setEnvironment(this.getEnvironment());
    // 为 beanDefinition 读取器设置 资源加载器,由于本类的基类 AbstractApplicationContext
    // 继承了 DefaultResourceLoader,因此,本容器自身也是一个资源加载器
    beanDefinitionReader.setResourceLoader(this);
    // 设置 SAX 解析器,SAX(simple API for XML)是另一种 XML 解析方法。相比于 DOM,SAX 速度更快,占用内存更小。
    // 它逐行扫描文档,一边扫描一边解析。相比于先将整个 XML 文件扫描近内存,再进行解析的 DOM,SAX 可以在解析文档的
    // 任意时刻停止解析,但操作也比 DOM 复杂。
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

// 初始化 beanDefinition 读取器,该方法同时启用了 Xml 的校验机制
    initBeanDefinitionReader(beanDefinitionReader);
    // Bean 读取器真正实现加载的方法
    loadBeanDefinitions(beanDefinitionReader);
}

Spring 全家桶BeanDefinition资源定位解析-立哥技术相关推荐

  1. 优酷视频云技术解析-立哥技术

    前言:从15年开始,云计算就开始从领先概念慢慢落成实地, 视频云技术作为其中重要分支,得到了长足发展.今天是笔者的生日,也从技术发展角度解析下视频云的要点技术. 1.优酷视频云技术核心:Cache C ...

  2. Spring Boot 系统日志代码解析-立哥技术

    // 男儿何不把吴钩,收取关山五十州 public static LoggingSystem get(ClassLoader classLoader) {     // 获取系统属性     Stri ...

  3. 智能汽车雷达解析-立哥技术

    前言:汽车行业是我国的支柱产业之一,也是上海的支柱产业.上海的辉煌,既是欧风美雨的产物,也是一代代中国人奋斗的结晶.除了特斯拉在临港设立的"亚洲第一超级工厂",上汽也和美国.德国等 ...

  4. osgi框架和spring区别_最全153道Spring全家桶面试题,你都知道哪些?(含答案解析)...

    前言 Spring 框架自诞生以来一直备受开发者青睐,有人亲切的称之为:Spring 全家桶. 毋庸置疑,Spring 早已成为 Java 后端开发的行业标准,无数的公司选择 Spring 作为基础的 ...

  5. 自己总结Spring全家桶面试题(3)

    Spring全家桶 一,spring 1,什莫是spring框架,使⽤有什么好处 ,谈谈你对Spring的理解 Spring是一个轻量级的java开发框架.简化了企业应用开发.Spring的出现是为了 ...

  6. Redis+分布式+设计模式+Spring全家桶+Dubbo阿里P8技术精选文档

    最近花了很长的时间去搜罗Java核心技术好文,我把每个Java核心技术的优选文章都整理成了一个又一个的文档.昨天也是终于全部整理好了,今天就把这些东西分享给老铁们,也能为老铁们省去不少麻烦,想学什么技 ...

  7. Spring全家桶面试题(四)之SpringCloud

    Spring全家桶面试题(四)之SpringCloud 十.微服务 88. 微服务架构的优缺点 1.分工协作 2.并发能力 3.维护能力(维护困难) 4.缺点 89. SOA.分布式.微服务之间有什么 ...

  8. Spring全家桶--SpringCloud(高级)

    Spring全家桶--SpringCloud(高级) 前言 一.SpringCloud alibaba 1.1 简介 1.2 主要功能 1.3 组件 1.4 资源获取 二.Nacos 2.1 Naco ...

  9. Spring全家桶小册,源码实战都有

    对于Java工程师来说,几乎没有没听过大名鼎鼎的Spring框架的,Spring框架早已成为了Java后端开发事实上的行业标准,可以说,是Spring成就了Java,Spring也成为Java程序员必 ...

最新文章

  1. VS.Net中程序集的Debug版本和Release版本的区别
  2. 自制Ghost XP SP3 启动光盘(一)
  3. Broadcast Receiver广播接收器
  4. 题目1206:字符串连接
  5. Zapcc:一个更快的C++编译器
  6. 【深度学习】擦除:提升 CNN 特征可视化的 3 种重要手段
  7. 解析xml的4种方法详解
  8. cobbler get-loaders 通过代理下载
  9. 使网页成黑白色调的滤镜(转)
  10. mysql5.0无法访问_MYSQL版本升级到后5.0后无法连接的问题
  11. [转载] python.day02笔记
  12. 计算机研究生可以参加哪些比赛?
  13. AngularJs ngList、ngRepeat、ngModelOptions
  14. 迅雷下gho文件变成php,GHO格式文件转换成WIM格式文件
  15. Cache tier使用文档
  16. 英语各类词担任的句子成分
  17. cogs2790. mk和tree解题报告
  18. 大学计算机基础案例教程章测试答案,大学计算机基础案例教程--Win7+Office2010(高等院校公共基础课规划教材)...
  19. 学会使用help()
  20. 中秋节到了,为什么你不回家?

热门文章

  1. 嵌入式开发第44天(GPIO的使用)
  2. 判刑形状模型_离散形状建模示规范表面模型.doc
  3. Tile Forward Shading
  4. IM学习-Openfire管理界面(四)
  5. 50Hz双T陷波滤波器(带阻滤波器)
  6. c++知识从无到有(持续更新)
  7. Unity报错 cleaning the mesh failed
  8. 山东大学软件学院2022大三下学期区块链技术期末考试回忆
  9. 基于Arduino3路循迹小车
  10. 组件 {B31118B2-1F49-48E5-B6F5-BC21CAEC56FB} 的事件解决方法