zoukankan      html  css  js  c++  java
  • spring源码系列(十): 读取xml入口类 ClassPathXmlApplicationContext 分析

    环境准备:

    使用spring5.1.6版本

    1 xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <bean id="user" class="com.hou.spring.bean.User"></bean>
    </beans>

    2 测试类

    public class BeanTest{
    
        @Test
        public void beanTest(){
            //spring4之后XmlBeanFactory被废弃,改用以下方式
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");
            User user = (User) applicationContext.getBean("user");
            System.out.println(user);
        }
    }

    然后点进去源码,跟着一步步debug来分析:

    1 构造器调用:

    ClassPathXmlApplicationContext的构造器中调用类同名方法:

     点击this跳转到初始化方法:

    2 super()方法是一直到父类AbstractApplicationContext中,将ApplicationContext的环境属性设置给本类的环境属性,包括一些profile,系统属性等

    3 setConfigLocations方法也是调用父类方法,将xml配置文件名字设置给父类的String数组属性

    4 refresh() 方法,所有的逻辑其实都在这个方法里面进行,主要分析这个方法:

    5 prepareRefresh主要还是环境属性的一些初始化,主要看第二步:

    // Tell the subclass to refresh the internal bean factory. 告诉子类刷新内部bean工厂
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    点进去obtainFreshBeanFactory:

    6 首先看refreshBeanFactory方法,注意,如果不知道是哪个子类的话,可以跟着debug断点走:

    主要分为这么几个步骤:

    一 首先判断本类的DefaultListableBeanFactory属性是否为null,如果不为null,就先清除一写跟Bean有关的Map或者List等属性集合

    二 将BeanFactory设置为null,序列化id设置为null,
    三 创建DefaultListableBeanFactory,这个类很重要,是springBean初始化的核心类,
    四 对beanFactory进行设置,bean注册等操作,最后将beanFactory赋值给本类的beanFactory属性

     7 customizeBeanFactory(beanFactory); 只做了两件事:

    8 loadBeanDefinitions:   Bean的注册主要是在这一步进行,下面进行分析,这个方法有5个子类实现:

    我写的测试类不是Web项目,所以会进入AbstractXmlApplicationContext这个类里的方法,如果是Web项目,会走XmlWebApplicationContext:

     首先创建XmlBeanDefinitionReader:xml配置读写器然后设置环境属性以及资源加载器为ClassPathXmlApplicationContext,这个加载器很重要,后面会用到

    接着初始化读取器: initBeanDefinitionReader,最后加载Bean

    8 initBeanDefinitionReader

    这个方法默认实现是空的,允许用户自定义实现读取器的定制化,需要实现接口,可以设置xml解析完成校验,定制化解析器等

    9 loadBeanDefinitions: 加载Bean信息,点进去:

    这个方法主要是加载类的两个资源属性,Resource[] 和xml位置信息,主要看加载Xml的:

    10 reader.loadBeanDefinitions(configLocations);

    循环加载xml文件的Bean返回Bean总个数,查看加载方法:

    11 查看这个load方法:

    这里需要注意第八步设置的加载器,查看加载器的时序图:

    因为有继承关系所以直接进if分支,继续分析if分支代码:

    主要步骤:

    1 获取加载器中的Resource[] 数组

    2 加载资源中的Bean,返回加载数量

    12 查看loadBeanDefinitions,循环加载了所有的资源,返回总数

    13 查看单个加载方法loadBeanDefinitions,主要看中间一段逻辑:

    这里对正在解析的xml资源放入ThreadLocal中,保证只有本次线程可以访问,加载完之后再移除

    13 查看doLoadBeanDefinitions(inputSource, encodedResource.getResource());

    
    
  • 相关阅读:
    2014编程之美资格赛 第二题 大神和三个小伙伴
    操作系统PV操作——进程同步问题(C#实现)
    [转_管理]成功者必备的15种能力
    [技术相关]List、Dictionary转Dictionary的性能分析
    [项目管理]怎样评定软件开发成果的质量
    Visual Studio 2013 RTM 中文语言包官方下载地址发布
    IIS7报错:如果要使用托管的处理程序,请安装 ASP.NET
    HTTP请求方式中get和post的区别
    asp.net之动态页面和静态页面的区别
    HTML语言语法大全
  • 原文地址:https://www.cnblogs.com/houzheng/p/11188974.html
Copyright © 2011-2022 走看看