Spring源码--IOC的初始化过程--03

Spring源码--IOC的初始化过程--03

一、前言

  1. 最近开始重温Spring,觉得只知道会用是不行的,所以想尝试着结合资料观摩一下源码
  2. 由于Spring源码非常的多,一步步都看完明显是不现实的,所以只记录自己觉得重要的步骤,其它细枝末节不去纠结
  3. 本人才疏学浅,以下的总结完全主观,在逐渐学习的过程中也会不断更新表述不合适的地方,如果有错误希望能包涵并指出!

二、源码阅读

  1. 接着02博客,到doLoadBeanDefinitions(inputSource, encodedResource.getResource())
    在这里插入图片描述
  2. doLoadBeanDefinitions
    1. 进来首先执行doLoadDocument来获得一个Document对象,点进去看看
      在这里插入图片描述
    2. 进来后先读注释:使用配置的DocumentLoader实际加载指定的文档。documentLoader对象是在初始化该类XmlBeanDefinitionReader的时候就创建好了的,实例为DefaultDocumentLoader,调用该对象的loadDocument去解析文件,传入了5个参数,一个个看
      在这里插入图片描述
      1. inputSource:包含解析文件信息的IO流对象
      2. getEntityResolver():获得XmlBeanDefinitionReader中的entityResolver属性,该属性是我们在初始化xml解析器时设置的,里面主要包含xml中相关的xsd
        在这里插入图片描述
      3. errorHandler:出现错误时的处理类
      4. getValidationModeForResource(resource):进入该方法,由上面的注释我们知道这是决定给定资源验证模式的,VALIDATION_AUTO和VALIDATION_XSD都是int类型的final常量,决定相应验证方法的,同时由注释知道我们也可以自己指定验证模式通过覆写该方法
        在这里插入图片描述
      5. isNamespaceAware():返回XML解析器是否应支持XML命名空间(false)
        在这里插入图片描述
    3. 进入loadDocument方法,里面主要就是通过工厂构建DocumentBuilder对象,用该对象去解析配置文件,具体解析过程就不点进去看了,看不懂…
      在这里插入图片描述
    4. 回到doLoadBeanDefinitions,执行完doLoadDocument后返回了一个Document对象,在控制台查看该对象,发现此时已经把配置文件相关信息都放进去了
      在这里插入图片描述
    5. 有了Document对象后,开始注册BeanDefinitions,将创建好的doc对象和资源对象传入,返回一个int值,由下面的代码我们指定该count代表的就是一共有多少个注册的bean对象,进入该方法
      在这里插入图片描述
    6. 进入后先是构造了一个BeanDefinitionDocumentReader对象,然后调用getRegistry().getBeanDefinitionCount()获得之前注册的bean对象个数,点进该方法看看
      在这里插入图片描述
    7. getRegistry方法,返回AbstractBeanDefinitionReader类中的registry属性,该属性是我们在实例化XmlBeanDefinitionReader时,由它调用父类AbstractBeanDefinitionReader的构造方法时设置的,实例为DefaultListableBeanFactory
      在这里插入图片描述
    8. getBeanDefinitionCount就是获得DefaultListableBeanFactory类中beanDefinitionMap的个数,但显然我们之前没有注册过bean,所以此时返回0
      在这里插入图片描述
    9. 由创建的BeanDefinitionDocumentReader调用方法开始注册bean,此时第二个参数为创建一个XmlReaderContext实例,不看创建步骤了,进入该方法
      在这里插入图片描述
    10. 进入到了DefaultBeanDefinitionDocumentReader类中,先把创建好的XmlReaderContext实例赋给该类的readerContext属性,之后调用doRegisterBeanDefinitions,继续进入
      在这里插入图片描述
    11. 进来先尝试获得DefaultBeanDefinitionDocumentReader类中的delegate属性,这个属性我们之前没有设置过,返回null
      在这里插入图片描述
    12. 返回了null对象后,下一步就是创建delegate属性了,点进去看看
      在这里插入图片描述
    13. 通过BeanDefinitionParserDelegate的构造方法去实例化该对象并返回,此时我们并不是很确定delegate属性代表的是什么,点BeanDefinitionParserDelegate类中看看
      在这里插入图片描述
    14. 发现该类中定义了很多常量,都是我们在配置文件时常用的配置属性,所以此时我们可以推断delegate属性中肯定有包含解析时用于匹配相应属性的容器
      在这里插入图片描述
    15. 回到doRegisterBeanDefinitions方法中,用创建的delegate属性去验证传入的是否是一个根对象,document对象显然是,进入if,里面做了一些判断,其实什么都没干,跳过到下面的preProcessXml
      在这里插入图片描述
    16. 点进preProcessXml(root)方法和postProcessXml(root)方法,发现里面也是什么都没干,这2个方法也是留给子类做扩展的,用于在注册bean前和注册bean后干点事
      在这里插入图片描述
    17. 进入parseBeanDefinitions方法,先是通过getChildNodes获取到传入的根节点中的所有子元素,之后开始遍历
      在这里插入图片描述
    18. 遍历的时候有2种情况,第一种是DefaultElement,即默认标签(不引入命名空间也可正常使用的标签),其它的都是CustomElement,我们在配置文件中先配置的是注解扫描,也就是<context:component-scan base-package=“com.hcc”/>所以先进入else中,进入该方法
      在这里插入图片描述
    19. 去到了BeanDefinitionParserDelegate类中,里面由调用了重载方法,多了一个参数null,继续往下走
      在这里插入图片描述
    20. 由上面定义的形参我们知道传入的null是一个BeanDefinition对象,该方法第一步获取到namespaceUri,即该配置对应的是哪一个命名空间
      在这里插入图片描述
    21. 解析namespaceUri,去获得相应的处理器handler,注意:不同的命名空间会有不同的处理器,具体可以在命名空间对应的源码目录下的MTEA-INF/spring.handlers文件中查看,之后调用处理器的parse方法继续解析
      在这里插入图片描述
    22. 里面通过findParserForElement方法获得具体的解析类,在同一个命名空间中,不同的标签也会对应不同的解析类,之后调用解析类的parse方法解析对应标签,所有解析类在解析完后都会将标签信息封装成BeanDefinitionHolder对象,并将其注册到工厂中
      在这里插入图片描述
    23. 将beanDefinition对象注册到工厂中,进入该方法
      在这里插入图片描述
    24. 一路往下走最终回到了我们熟悉的DefaultListableBeanFactory类中,将刚创建好的beanDefinition添加到工厂容器中,注意:此时所有注册的对象实例还没有创建,只是往容器中添加了bean信息
      在这里插入图片描述
    25. 因为我们只有一个对象需要注册,所以在工厂添加完后便一路返回,最终回到parseBeanDefinitions中,解析下一个document对象在这里插入图片描述
    26. 当所有的document对象解析完成后,就会一路返回最终回到refresh方法中,工厂对象就创建完了,现在我们知道obtainFreshBeanFactory语句不仅仅时创建工厂,其中还包括解析xml文件,将bean信息注册到工厂中在这里插入图片描述
    27. 边看边写太累了/(ㄒoㄒ)/~~,后续的只画图算了,有需要的下面网址自取

三、图像总结

在这里插入图片描述
链接:https://pan.baidu.com/s/1_3dNVCsFp7o1_KzS9FYdPA
提取码:7wt8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值