• Spring源码学习——解析xml节点


    核心文件:BeanDefinitionParserDelegate

    • 以下内容为本人有道笔记内容迁移

    1:处理默认节点

    DefaultBeanDefinitionDocumentReader类的parseBeanDefinitions用来处理解析出来的dom元素;针对4个默认的标签走parseDefaultElement方法(beans,bean,alias,import)

    1.1 bean节点

    • 入口:BeanDefinitionParserDelegate.processBeanDefinition方法

    1.1.1转换为beanholder

    • 入口:BeanDefinitionParserDelegate.parseBeanDefinitionElement方法
    1.1.1.1 :校验beanname是否在set中存在,并且将beanname放入一个set缓存,其中包含所有已经处理过的bean的name;
    • 入口:BeanDefinitionParserDelegate.checkNameUniqueness

    1.1.1.2 通过element创建beandefinition(核心)

    入口:BeanDefinitionParserDelegate.parseBeanDefinitionElement方法

    1.1.1.2.1:创建abstractbeandefinition
    • 入口:BeanDefinitionParserDelegate.createBeanDefinition(className, parent)
    • 实际执行方法:
      BeanDefinitionReaderUtils.createBeanDefinition:创建GenericBeanDefinition实体,设置beanclass返回

    1.1.2 decorateBeanDefinitionIfRequired

    • 装饰bean,默认标签下不做深入解析
    • 查看后发现,对于默认标签没有处理,非默认标签需要获取对应的handler之后调用他的decorate方法

    1.1.3 registerBeanDefinition

    • 注册bean到beanfactory
      -实质上是调用beanfactory的registerBeanDefinition方法(默认为DefaultListableBeanFactory)
    • 进入方法后可以看到:首先通过beanname从一个名为beanDefinitionMap的ConcurrentHashMap中查询是否存在(debug发现beanname来自于id或name,如果没有设置则用class加上#序号作为beanname)
    1.1.3.1:如果不在beanDefinitionMap中并且beanfactory还没开始创建bean

    1)加入beanDefinitionMap
    2)加入beanDefinitionNames(arraylist)
    3)移除手工添加的单例bean

    如果已经开始创建bean:
    1)加入beanDefinitionMap
    2)将beanDefinitionNames(arraylist)移入一个新的arraylist并加入该条
    3)移除手工添加的单例bean

    1.1.3.2:如果在beanDefinitionMap中

    首先判断beanfactory是否允许复写(override),如果允许则直接覆盖写入beanDefinitionMap。

    bean节点解析完成:最终创建的beandefinition放在了map中,内部还有一个arraylist存放beanname

    2:处理非默认节点(重点)

    • 入口:BeanDefinitionParserDelegate M:parseCustomElement

    2.1 context:component-scan

    • 解析非默认节点的处理方法:BeanDefinitionParserDelegate内
    • 每个类型节点对应的解析类,在对应jar包的META-INF/spring.handlers目录下定义;

    2.1.1 获取解析该类节点的handler

    • 以context为例,对应的contextjar包下指明他的解析类为ContextNamespaceHandler,通过resolve方法直接获取handler的实例;

    2.1.2 获取该节点明细的parser

    • 通过handler的init方法,定义该namespace下的明细节点处理类,放在map缓存。本例为ComponentScanBeanDefinitionParser

    2.1.3 通过获取的parser解析该节点

    • 在doScan方法中将扫描出来的bean注册;
      registerComponents中注册多个BeanPostProcessor接口实现类,供后续spring调用统一接口进行解析

    通过base-package属性,解析到机器上的class的实际绝对地址根路径

    如果是jar包,则通过扫描器Scanner对jar进行解析,获取class;

    解析获取到所有的class之后,通过typefilter过滤等,剩下满足条件可以被处理为bean的class;

  • 相关阅读:
    linux centos&Ubuntu&RedHat更换软件源
    linux及windows安装maven
    No converter found for return value of type: class com.alibaba.fastjson.JSON解决办法
    linux sudo命令失败 提示sudo:/usr/bin/sudo 必须属于用户 ID 0(的用户)并且设置 setuid 位
    Linux常用命令
    Linux安装Java+Eclipse或IDEA
    Python基础编程:字符编码、数据类型、列表
    linux系统挂载u盘拷贝文件
    linux(服务器)如何确认网卡(网口)对应的配置文件
    Python第三方库requests的编码问题
  • 原文地址:https://www.cnblogs.com/ForsakenCoder/p/13046711.html
Copyright © 2020-2023  润新知