• 创建ApplicationContext与BeanFactory时的区别-Spring源码学习之容器的基本实现


    传送门

    可以加载XML两种方法

    使用 BeanFactory 加载 XML

    BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicaitonContext.xml"));
    

    Ps:因为我是跟着《Spring源码深度解析》学习的,而这本书出版在13年9月,这一种方法在新的Spring版本中已经废弃掉了,取而代之的是下面的方法;但既然学了,那就还是记录一下,学习一下开发者的思想也是不错的.

    使用 ApplicationContext 加载 XML

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    

    相同点

    上述两者都是通过加载XMl配置文件的方式加载Bean,而后者是前者的扩展,提供了更多的功能,即ApplicationContext拥有BeanFactory的全部功能,在绝大多数的"典型的"企业应用和系统,ApplicationContext都优先于BeanFactory.

    不同点

    BeanFactory是延迟加载,如果一个Bean当中存在属性没有加载,会在第一次调用getBean()方法的时候报错,而ApplicationContext会在读取Xml文件后,如果配置文件没有错误,就会将所有的Bean加载到内存中,缺点就是在Bean较多的时候比较占内存,程序启动较慢.

    Spring容器加载中最重要的两个类

    DefaultListableBeanFactory

    XmlBeanFactory继承自DefaultListableBeanFactory,而后者是整个Bean加载的核心部分,是Spring注册及加载Bean的默认实现,而XmlBeanFactory使用了自定义的Xml读取器XmlBeanDefinitionReader,实现了个性化的BeanDefinitionReader读取.

    XmlBeanDefinitionReader

    主要负责Xml文件的读取、解析和注册功能


    加载时的区别

    上面的两种方法的处理大致相同,让我们通过时序图看看两者在加载时的区别:

    BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicaitonContext.xml"));
    

    粗略时序图:

    image
    首先,将applicationContext.xmlClassPathResource进行封装得到Resource资源,Resource接口将所有的资源文件统一处理,当通过Resource相关类完成了对配置文件的封装之后,就由XmlBeanDefinitionReader进行读取和解析.

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    

    粗略时序图:

    image
    附上ClassPathXmlApplicatioContext构造函数的源码:

    public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
    			throws BeansException {
    
    		super(parent);
    		Assert.notNull(paths, "Path array must not be null");
    		Assert.notNull(clazz, "Class argument must not be null");
    		this.configResources = new Resource[paths.length];  //创建资源数组  private Resource[] configResources;
    		for (int i = 0; i < paths.length; i++) {
    			this.configResources[i] = new ClassPathResource(paths[i], clazz);
    		}
    		refresh();  //解析工作,ClassPathXmlApplicatioContext继承来自AbstractApplicationContext中的方法
    	}
    

    首先,同样是封装配置文件,但封装完成之后并没有直接进行读取,而是调用了refresh()方法(这个方法里面进行了很多操作,扩展的功能几乎是在这里面实现的),refresh()方法中的obtainFreshBeanFactory()方法负责初始化BeanFactory,并对XMl文件读取,读取的核心实现是该方法中调用的refreshBeanFactory()方法,这个方法再调用图中的loadBeanDefinitions(beanFactory)方法(由于板面原因,没有画出),然后在其中创建XmlBeanDefinitionReader对象,再将最初封装的资源文件数组进行依次读取并解析.

    二者在后面的Xml解析工作都几乎是一样的,都采用了SAX解析,区别就在于解析之前的准备和解析之后的完善工作.

  • 相关阅读:
    开发工具分享
    图形学杂记
    keyle的Shader-学习手札
    Keyle的3D数学-学习手札
    SuperStrange项目主页
    Unity3d基础知识(水文)
    和Keyle一起学ShaderForge – Custom Blinn-Phong
    和Keyle一起学ShaderForge – Create Base Shader
    和Keyle一起学ShaderForge
    和Keyle一起学StrangeIoc – 教程目录
  • 原文地址:https://www.cnblogs.com/yuanmiemie/p/6812163.html
Copyright © 2020-2023  润新知