前言

上一篇文章讲述了ApplicationContext扩展功能的之一:环境准备。这篇文章接着讲述ApplicationContext的扩展功能-----加载BeanFactory,也就是初始化BeanFactory,并进行XML文件的读取。

加载BeanFactory

obtainFreshBeanFactory方法从字面上的意思就是获取BeanFactory。之前说过,ApplicationContext是对BeanFactory的功能上的扩展,不但包含了BeanFactory的全部功能更在其基础上添加了大量的扩展应用,那么obtainFreshBeanFactory正是实现BeanFactory的地方,也就是经过了这个函数,ApplicationContext就已经拥有了BeanFactory的全部功能。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {//初始化beanFactory,并进行XML文件的读取,并将得到的BeanFactory记录在当前实体的属性中
        refreshBeanFactory();//返回当前实体的BeanFactory属性return getBeanFactory();}

protected final void refreshBeanFactory() throws BeansException {if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {//创建DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();//为了序列化指定ID,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象
            beanFactory.setSerializationId(getId());//定制BeanFactory,设置相关的属性,包括是否覆盖同名称的不同定义的对象以及循环依赖以及设置@Autowire和@Qualifier注解解析器
            customizeBeanFactory(beanFactory);//初始化DocumentReader,并进行XML文档的读取与解析
            loadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}}

我们来详细分析上面第二段代码的步骤:

(1)创建DefaultListableBeanFactory。

  在介绍BeanFactory的时候,曾经提到过,声明方式为:BeanFactory bf = new XmlBeanFactory("spring.xml");,其中的XMLBeanFactory继承自DefaultListableBeanFactory,并提供了XmlBeanDefinitionReader类型的reader属性,也就是说DefaultListableBeanFactory是容器的基础。必须要首先实例化,那么在这里就是实例化DefaultListableBeanFactory的步骤。

(2)指定序列化id。

(3)定制BeanFactory。

(4)加载BeanDefinition。

(5)使用全局变量记录BeanFactory类实例。

因为DefaultListableBeanFactory类型的变量BeanFactory是函数类的局部变量,所以要使用全局变量记录解析结果。

接下来对上述的一些步骤进行详细的解析:

定制BeanFactory

这里已经开始了对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖是否允许扩展的设置并提供了注解@Qualifier和@Autowire的支持。

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {//如果属性allowBeanDefinitionOverriding不为空,设置给BeanFactory对象相应的属性,此属性的含义:是否允许覆盖同名称的不同定义的对象if (this.allowBeanDefinitionOverriding != null) {beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}//如果属性allowCircularReferences不为空,设置给BeanFactory相应的属性,此属性的含义:是否允许bean之间存在循环依赖if (this.allowCircularReferences != null) {beanFactory.setAllowCircularReferences(this.allowCircularReferences);}}

上述代码对于允许覆盖和允许依赖的设置这里只是判断了是否为空,如果不为空要进行设置,但是并没有看到在那里进行设置,究竟这个设置是在那里进行设置的呢?还是那句话,使用子类覆盖方法,例如:

public class MyClassPathApplicationContext extends ClassPathXmlApplicationContext {@Overrideprotected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {super.setAllowBeanDefinitionOverriding(false);super.setAllowCircularReferences(false);super.customizeBeanFactory(beanFactory);}
}

 加载BeanDefinition

在上述代码的第一步中提到了将ClassPathXmlApplicationContext与XMLBeanFactory创建的对比,在实现配置文件的加载功能中除了我们第一步中已经初始化的DefaultListableBeanFactory外,还需要XmlBeanDefinitionReader来读取XML,那么在这个步骤中首先要做的就是初始化XmlBeanDefinitionReader。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {//为指定BeanFactory创建XmlBeanDefinitionReaderXmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// 对BeanDefinitionReader进行环境变量的设置beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));//对BeanDefinitionReader进行设置,可以覆盖
        initBeanDefinitionReader(beanDefinitionReader);loadBeanDefinitions(beanDefinitionReader);}

在初始化了DefaultListableBeanFactory和XmlBeanDefinitionReader后就可以进行配置文件的读取了。

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {Resource[] configResources = getConfigResources();if (configResources != null) {reader.loadBeanDefinitions(configResources);}String[] configLocations = getConfigLocations();if (configLocations != null) {reader.loadBeanDefinitions(configLocations);}}

使用XmlBeanDefinitionReader的loadBeanDefinitions方法进行配置文件的加载及注册。这跟BeanFactory的套路是一致的。因为在XmlBeanDefinitionReader中已经将之前初始化的DefaultListableBeanFactory注册进去了,所以XmlBeanDefinitionReader所读取的BeanDefinitionHolder都会注册到DefaultListableBeanFactory中,也就是经过此步骤,类型DefaultListableBeanFactory的变量BeanFactory已经包含了所有解析好的配置。

 参考:《Spring源码深度解析》  郝佳 编著:

转载于:https://www.cnblogs.com/Joe-Go/p/10211289.html

加载BeanFactory相关推荐

  1. Spring容器创建流程(2)创建beanFactory,加载BeanDefinition

    Spring 容器的创建.obtainFreshBeanFactorr()中完成容器的创建.(BeanFactory关系类图,之前的执行流程可在本系列博客中看到).接下来看容器创建的第二部,创建bea ...

  2. Spring解析,加载及实例化Bean的顺序(零配置)

    点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 作者:jb_hz blog.csdn.net/qq_2752 ...

  3. 看看Spring的源码(一)——Bean加载过程

    首先Web项目使用Spring是通过在web.xml里面配置 org.springframework.web.context.ContextLoaderListener初始化IOC容器的. <l ...

  4. Spring容器和Bean加载

    Spring容器的IOC和DI概念 IOC(控制反转):对于组件的控制权进行了转移,传统的程序设计是由客户端new出对象,是程序主动创建所依赖的对象.而IOC是专门将对象的创建交给容器处理,组件的控制 ...

  5. 【Spring源码分析系列】bean的加载

    前言 以 BeanFactory bf  = new XmlBeanFactory(new ClassPathResource("beans.xml"));为例查看bean的加载过 ...

  6. Spring中加载xml配置文件的六种方式

    Spring中加载xml配置文件的六种方式 博客分类: Spring&EJB XMLSpringWebBeanBlog  因为目前正在从事一个项目,项目中一个需求就是所有的功能都是插件的形式装 ...

  7. Spring IOC 之 加载 Bean

    2019独角兽企业重金招聘Python工程师标准>>> 这段代码是 Spring 中编程式使用 IOC 容器,通过这四段简单的代码,我们可以初步判断 IOC 容器的使用过程 获取资源 ...

  8. spring boot 加载过程分析(三)

    接着上一篇,现在主要来看一下prepareContext方法的内容,先看代码: prepareContext执行过程 private void prepareContext(ConfigurableA ...

  9. 面试官:讲讲Spring框架Bean的加载过程

    spring作为目前我们开发的基础框架,每天的开发工作基本和他形影不离,作为管理bean的最经典.优秀的框架,它的复杂程度往往令人望而却步. 不过作为朝夕相处的框架,我们必须得明白一个问题就是spri ...

最新文章

  1. 神经网络 | 玻尔兹曼机(附python源代码)
  2. Laravel核心代码学习--用户认证系统(基础介绍)
  3. 计算机报名显示事务已被锁死,ORA-01591错误处理: 锁定已被有问题的分配事务处理20.18.156406挂起(转载)...
  4. php中的ol标签,html5中ol标签的用法详解
  5. python爬虫自动更换ip_Python 爬虫使用动态切换ip防止封杀
  6. 十字路口红绿灯plc程序_PLC编程-典型案例红绿灯控制
  7. phantomjs执行常见错误
  8. PatchGAN:Image-to-Image Translation with Conditional Adversarial Networks
  9. java yyyymmddThhmiss_如何在Javascript中以mm-dd-hh格式获取两个日期的差
  10. diabetes影响因子2017_2017年SCI影响因子发布,几家欢喜几家愁
  11. 【GMSK+FPGA】基于verilog的GMSK调制系统设计
  12. 从计算机视觉到人脸识别:一文看懂颜色模型、信号与噪声
  13. 模拟摄影测量和数字摄影测量
  14. 用Matplotlib绘制渐变的彩色曲线
  15. VideoCapX Video Crack,保存和访问这些视频和图像的需求
  16. iOS7新特性 ViewController转场切换(二) 系统视图控制器容器的切换动画---push pop present dismis
  17. 学计算机的演员,南开大学计算机系到演员 张桐回顾“不安分”的青春_TOM明星...
  18. P5490 【模板】扫描线
  19. opencv创建负片
  20. IEEE | DSConv: Efficient Convolution Operator

热门文章

  1. 区块链还能赚钱吗 区块链挖矿赚钱吗
  2. mysql查询解析过程_MySQL查询执行过程详解
  3. 控制行输入以下两句命令16倍速播放青年大学习
  4. 1107 Social Clusters
  5. 1066 Root of AVL Tree 需再做
  6. (C++)1002 写出这个数
  7. (C++) CSP 201803-1 跳一跳
  8. Oracle数据库的逻辑结构和存储层次
  9. 找Java培训机构需要注意那些
  10. 自定义通知与系统通知的学习(详解)