Spring Xml解析全链路分析

当我们在符合spring schema的xml中配置了我们定义的javaBean,spring就可以将bean装载到spring容器当中。那么这中间经历了哪些过程呢,一起来看一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?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="person" class="com.liyl.study.java.bean.Person" />
</beans>

/**
 * description: java bean
 * auther: liyonglong
 * date: 2020/9/6
 */
public class Person {

    private Long id;
    private Byte gender;

    public Person() {
        System.out.println("每一个人都会经历出生");
    }
}


public class Entrance {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/spring_bean.xml");
        Person person = applicationContext.getBean(Person.class);
    }
}

下图为主要脉络:
通过资源Resource相关类读取资源,然后解析为BeanDefinition类描述信息,最后注册到Spring容器当中


先来认识Resource

Resource讲解

Resource家族,实现了对不同资源的访问策略


AbstractResource实现了接口Resource中定义的大部分对资源文件的通用处理方法


Spring通过给定的文件路径就能够返回对应的Resource实现类,比如Ant通配符。classpath、file等前缀,这归功于ResourceLoader,里面定义了getResource()方法和getClassLoader()方法

ResourceLoader家族

那么,ResourceLoader和Spring容器会有一个什么样的联系呢,请看下图,
上下文ApplicationContext继承了ResourcePatternResolver,而ResourcePatternResolver正是ResourceLoader的子接口,这也是为什么我们能通过ClassPathXmlApplicationContext就可以读取到资源文件并进行解析。
ResourcePatternResolver用来解析classpath*前缀的路径的,具体实现由实现类PathMatchingResourcePatternResolver实现。


ResourceLoader的使用者 - - BeanDefinitionReader

BeanDefinitionReader正是使用ResourceLoader读入资源文件并解析成BeanDefinition实例,然后注册到容器当中。
先来看接口定义,主要就是getBeanClassLoader读取输入流,然后就是loadBeanDefinitions的各个重载方法

BeanDefinitionReader家族谱

通过xml方式配置,着重关注XmlBeanDefinitionReader实现


首先,由AbstractBeanDefinitionReader的实现中获取ResourceLoader实例
然后,通过不同的ResourceLoader实例去执行不同的loadBeanDefinitions()方法,通常都是ResourcePatternResolver,上面说过,他是加载多个资源文件的,解析classpath*前缀的路径就是使用这个实现。然后一路点进去就会进入XmlBeanDefinitionReader实现的loadBeanDefinitions方法
如图

  1. 获取ResourceLoader实例
    2.执行loadBeanDefinitions方法,这是个抽象方法,需要子类实现


    XmlBeanDefinitionReader中的doLoadBeanDefinitions方法就是真正的解析xml的方法,会将xml文件流解析成Document对象,然后将Document对象解析成BeanDefinition进行注册

解析为Document对象,然后由registerBeanDefinitions方法去解析Document


解析Document


进入这里,继续进入方法,去解析document对象

然后就进入到这里