记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新。欢迎大家指正!

环境: spring5.X + idea

Spring 是一个工厂,是一个负责对象的创建和维护的工厂。它给我提供了一个功能齐全而且方便我们使用的ApplicationContext子接口,它最底层的接口是BeanFactory。在这个BeanFactory下面衍生了各种功能的子接口。

  1. 容器管理HierarchicalBeanFatory
  2. 自动注入AutowireCapableBeanFactory
  3. 读取配置信息ListableBeanFactory

可以自行找一下BeanFactory类关系图,它有一个子实现类XmlBeanFactory,先说一下XML配置文件的读取

ListableBeanFactory 是读取配置信息的,它的子实现类XmlBeanFactory就是读取xml文件的具体实现。
而ApplicationContext继承了ListableBeanFactory并对xml解析做了进一步的封装所以再我们使用ApplicationContext
时直接给他一个对应位置的资源文件名它就会帮我们读取到配置信息。 ApplicationContext ctx = new ClassPathXmlApplicatiionContext("applicationContext.xml");
User user = ctx.getBean("user"); //我们直接用最底层的接口 BeanFactory 获取xml信息 BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
User user = bf.getBean("user");

说明:

  1. beanFactory 底层获取xml文件信息的实现类 XmlBeanFactory 需要传入一个 ClassPathResource 对象。这个对象的父接口就是InputStreamSource 他就是提供了一个获取输入流的方法
    InputStream getInputStream() throws IOException;

    而ClassPathResource 对这个方法的实现就是通过类或者类加载器实现的

    if (this.clazz != null) {
    is = this.clazz.getResourceAsStream(this.path);
    }
    else if (this.classLoader != null) {
    is = this.classLoader.getResourceAsStream(this.path);
    }

    获取了输入流那就自然可以获取文件的内容了。

  2. Spring获取xml内容后通过XmlBeanDefinitionReader解析配置文件的内容封装成BeanDefinition方便后续使用。
    //前边说了是XmlBeanFactory具体实现获取xml信息的功能
    1. public class XmlBeanFactory extends DefaultListableBeanFactory {
    //xmlBeanFactory 中直接实例化 xmlBeanDefinitionReader
    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
    .....
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
    super(parentBeanFactory);
    this.reader.loadBeanDefinitions(resource);
    }
    }
    2. public class XmlBeandefinitionReader extends AbstractBeanDefinitionReader{
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    ......
    try (
    //获取输入流
    InputStream inputStream = encodedResource.getResource().getInputStream()) {
    //xml 解析工具类
    InputSource inputSource = new InputSource(inputStream);
    if (encodedResource.getEncoding() != null) {
    inputSource.setEncoding(encodedResource.getEncoding());
    }
    //开始具体解析
    return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }
    ......
    }; protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {
    try {
    // xml 解析为 document
    Document doc = doLoadDocument(inputSource, resource);
    // document 转 beanDefinition
    int count = registerBeanDefinitions(doc, resource);
    if (logger.isDebugEnabled()) {
    logger.debug("Loaded " + count + " bean definitions from " + resource);
    }
    return count;
    }
    }
    }
    3. public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    protected void doRegisterBeanDefinitions(Element root){
    ...
    preProcessXml(root);
    parseBeanDefinitions(root,this,dalegate);
    postProcessXml(root);
    }; protected void parseBeanDefinitions(Element root,BeanDefinitionParseDelegate delegate){
    if (delegate.isDefaultNamespace(root)) {
    NodeList nl = root.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++) {
    Node node = nl.item(i);
    if (node instanceof Element) {
    Element ele = (Element) node;
    if (delegate.isDefaultNamespace(ele)) {
    //解析基本标签
    parseDefaultElement(ele, delegate);
    }
    else {
    //解析自定义标签
    delegate.parseCustomElement(ele);
    }
    }
    }
    }
    } }

    解释说明:

    1. 通过 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法得到输入流和xml解析工具类在 doLoadBeanDefinitions方法中把输入流也就是获得的xml文件信息转化为 Document 再通过 registerBeanDefinitions 方法封装成 beanDefinition
    2. 封装beanDefinition是在 DefaultBeanDefinitionDocumentReader 类中的doRegisterBeanDefinitions . parseBeanDefinitions方法做了具体功能的实现,也就是解析文件中的标签并和beanDefinition的属性做映射。例如: 根标签(beans、prefile等) 子标签 (基本标签 bean、import、alias等,自定义标签 aop、mvc:annotation-driven、tx:annotation-driven、context:等)
    3. 用 BeanDefinitionParserDelegate 把解析标签得到的值映射成beanDefinition方便后续使用。

最后

感谢您的阅读,有什么意见和问题欢迎评论区留言!书写不易!

觉得文章对你有帮助记得给我点个赞,欢迎大家关注和转发文章!

干货分享之Spring框架源码解析01-(xml配置解析)的更多相关文章

  1. 干货分享之spring框架源码分析02-(对象创建or生命周期)

    记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 之前分析了Spring读取xml文件的所有信息封装成beanDef ...

  2. Spring AMQP 源码分析 08 - XML 配置

    ### 准备 ## 目标 通过 XML 配置文件使用 Spring AMQP ## 前置知识 <Spring AMQP 源码分析 07 - MessageListenerAdapter> ...

  3. Spring源码-IOC部分-Xml Bean解析注册过程【3】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  4. Spring框架源码干货分享之三级缓存和父子工厂

    记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 建议:学习过程中要开着源码一步一步过 Spring中对象的创建宏观 ...

  5. Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)

    去年通过实际框架代码的阅读,以及结合<Spring源码深度解析>和<Spring技术内幕>的阅读,对Spring框架内Bean模块有了一个整体性的认识.对此进行的总结性整理和回 ...

  6. spring beans源码解读之--bean definiton解析器

    spring提供了有两种方式的bean definition解析器:PropertiesBeanDefinitionReader和XmLBeanDefinitionReader即属性文件格式的bean ...

  7. Spring MVC源码(四) ----- 统一异常处理原理解析

    SpringMVC除了对请求URL的路由处理特别方便外,还支持对异常的统一处理机制,可以对业务操作时抛出的异常,unchecked异常以及状态码的异常进行统一处理.SpringMVC既提供简单的配置类 ...

  8. 设计模式(五)——原型模式(加Spring框架源码分析)

    原型模式 1 克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10 只羊. 2 传统方式解决克隆羊问题 1) 思路分析(图 ...

  9. spring框架源码编译

    程序猿小菜一枚,最近从github上面下载下来一份spring各个项目的源码一份,但是弄了很长时间,因为网速和(fanqiang)的速度,希望大家不要再为这种无谓的时间花费时间,简单来说github上 ...

随机推荐

  1. 剖析虚幻渲染体系(11)- RDG

    目录 11.1 本篇概述 11.2 RDG基础 11.2.1 RDG基础类型 11.2.2 RDG资源 11.2.3 RDG Pass 11.2.4 FRDGBuilder 11.3 RDG机制 11 ...

  2. centos7 权限更改,所属用户及用户组更改

    2021-08-03 # 查看文件的权限 ll 第一个字符, "-" 表示是文件, "d" 表示是目录(directory) 后面 9 个字符每 3 个字符又作 ...

  3. AFL++初探-手把手Fuzz一个PDF解析器

    CVE-2019-13288 目前漏洞在正式版本已经被修复,本文章仅供学习Fuzz过程,不存在漏洞利用的内容 这是一个pdf查看器的漏洞,可能通过精心制作的文件导致无限递归,由于程序中每个被调用的函数 ...

  4. 第20篇-加载与存储指令之ldc与_fast_aldc指令(2)

    ldc指令将int.float.或者一个类.方法类型或方法句柄的符号引用.还可能是String型常量值从常量池中推送至栈顶. 这一篇介绍一个虚拟机规范中定义的一个字节码指令ldc,另外还有一个虚拟机内 ...

  5. TDSQL(MySQL版)之DB组件升级

    随着数据库产品的更新迭代,修复bug等等,产品避免不了会出现升级的需求.TDSQL(MysqL版)也会有这方面的需求.接下来我就说说如何对现有TDSQL(MySQL版)集群组件进行升级,而不影响业务. ...

  6. three+pixi 将二维和三维结合

    PIXI+THREE 使用 PIXI 和 THREE 将三维和二维渲染在同一个 canvas 下面 效果 思路 初始化 PIXI 的 Application, 作为 pixi 最重要的变量 const ...

  7. Mysql常用sql语句(10)- is null 空值查询

    测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 前言 is null是一个关键字来的,用于判断字段的值 ...

  8. Golang入门学习(二):控制分支

    文章目录 @[TOC] 1. 控制分支 1.1 if-else分支 1.2 switch分支 1.4 while 和do...while循环结构 1.5 多种循环结构 1.6 break 1.7 co ...

  9. AntDesign VUE:上传组件图片/视频宽高、文件大小、image/video/pdf文件类型等限制(Promise、Boolean)

    文件大小限制 - Promise checkFileSize(file, rules) { return new Promise((resolve, reject) => { file.size ...

  10. Nginx rewrite跳转 location匹配

    目录: 一.常用的Nginx 正则表达式 二.location 三.rewrite 一.常用的Nginx 正则表达式 1 ^ :匹配输入字符串的起始位置 2 $ :匹配输入字符串的结束位置 3 * : ...