专栏首页不会写文章的程序员不是好厨师Spring源码初探-IOC(1)-Bean的初始化

Spring源码初探-IOC(1)-Bean的初始化

前言

对于一名Java码农来说,Spring真是太重要了。目前Spring的体系已经发展得非常壮大,其底层基石core,beans,context非常牢固。

spring 体系结构图

Bean初始化

个人认为,Spring最原始或者最基础的功能是“容器”,帮你管理着一堆bean的生命周期,任你取用,要想更好的使用Spring,还是得了解Bean的整个生命周期,首先了解Bean的初始化过程。本文采用XML配置文件的方式管理bean,分析XmlBeanFactory对于XML文件的解析过程。废话不多说,先上图:

Spring XmlBeanFacotry解析XML过程(1).jpg

上图给出了XmlBeanFactory将xml配置解析成BeanDefinition的过程,最上面给出的类是在解析过程中涉及到的,首先大致进行一个介绍:

  • Resource:是spring对于资源的一种抽象,因为资源的来源可能很丰富,利于File,Class Path Resource,Url Resource等,进行统一封装,暴露出getInputStream进行统一读取解析
  • Document:这个没啥好讲的,XML文档对象
  • EncodedResource:封装了Resource,指定Resource的编码
  • ReaderContext:Bean Definition解析过程中的上下文对象,封装了Resource、ProblemReporter、EventListener、SourceExtractor等
  • Element:XML中的元素节点对象
  • BeanDefinition:这个接口及其实现类非常重要,他描述了XML中一个bean节点及其子节点的所有属性,将xml中的描述转变成内部的field信息,举例:scope,lazyinit,ConstructorArgumentValues(描述构造器),PropertyValues(描述属性值)等,是一个保罗万象的接口,其子类实现包括GenericBeanDefinition、RootBeanDefinition、ChildBeanDefinition等
  • BeanDefinitionHolder:顾名思义包含了一个BeanDefinition,同时其包含了beanName和aliases,更好的封装了一次
  • BeanDefinitionReader:定义了读取BeanDefinition的接口,主要作用是从Resource中读取Bean定义,XmlBeanDefinitionReader是其具体的实现类
  • BeanDefinitionDocumentReader:定义了从Document对象中解析BeanDefinition并且注册到Registry中设计到的接口,其默认实现类是DefaultBeanDefinitionDocumentReader,主要是被XmlBeanDefinitionReader委派去处理Document对象
  • BeanDefinitionParserDelegate:看到Delegate就知道这个哥们是个受苦的对象,是个最终干活的人,官方定义是“Stateful delegate class used to parse XML bean definitions.* Intended for use by both the main parser and any extension* {@link BeanDefinitionParser BeanDefinitionParsers} or* {@link BeanDefinitionDecorator BeanDefinitionDecorators}.”是用于最终处理XML bean定义的人,它做的可都是脏活累活,import/alias/bean等element以及element的子节点以及属性都是它解析并且填充到BeanDefinition中然后使用ReaderContext中的Registry(实际就是DefaultListableBeanFactory)来将该BeanDefinition注册
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {  
  if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {      importBeanDefinitionResource(ele);   }  
  else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {               processAliasRegistration(ele);   }  
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {      processBeanDefinition(ele, delegate);   }
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {      // recurse      doRegisterBeanDefinitions(ele);   }}

上述代码描述了BeanDefinitionParserDelegate对于不同element的解析,脏活累活中非常的一个部分

小结

本文算是小小地总结了一下将XML解析成BeanDefinition的过程中涉及到的一些类,将XML解析出来其实是一个很简单的过程,但是Spring却用了非常多的类。究其原因还是为了考虑扩展性,不断地抽象,不断地将责任委派。这篇文章只介绍了DefaultElement的解析,下篇文章将介绍怎么自定义标签以及Spring怎么解析自定义标签。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JVM Flags介绍-Heap相关

    以下的讨论的heap是这样的heap(堆):基于经典分类,分为young gen, old gen , permanent gen 。1.8已经没有perman...

    LNAmp
  • Spring源码初探-IOC(2)-Bean的初始化-自定义标签解析

    前面一文介绍的是Spring对于DefaultElement的解析,例如bean/import/alias等,但是在Spring体系中也存在很多扩展标签,例如事...

    LNAmp
  • ClassNotFoundException,NoClassDefFoundError,NoSuchMethodError排查

    在使用java开发的过程中时常会碰到以上三个错误,其中NoClassDefFoundError、NoSuchMethodError两个error遭遇得会多一些。...

    LNAmp
  • 显示 Uncaught TypeError: Cannot read property 'dialog' of undefined”的错误解决方法

    运行测试的时候,报了这一堆的错误Uncaught TypeError: Cannot read property 'dialog' of undefined”

    朱季谦
  • C# Socket 接受数据不全的处理

    do while 和while的区别 while和do…while语句都是循环语句,功能都差不多,唯一的区别在于检验条件的时间上。while语句在进入循环体之前...

    zls365
  • javascript转义unicode十六进制编码且带有反斜杠后的html

    由于后端返回的html代码中所有标签前后都有反斜杠“\”,且有\uxxxx形式的十六进制unicode编码,如果直接把所有反斜杠替换为%,则会把标签前后的反斜杠...

    蓓蕾心晴
  • 看了这篇文章,了解深度卷积神经网络在目标检测中的进展

    近些年来,深度卷积神经网络(DCNN)在图像分类和识别上取得了很显著的提高。回顾从 2014 到 2016 这两年多的时间,先后涌现出了 R-CNN,Fast ...

    AI研习社
  • .NET的资源并不限于.resx文件,你可以采用任意存储形式[下篇]

    在《上篇》中我们谈到ResourceManager在默认的情况下只能提供对内嵌于程序集的.resources资源文件的存取。为了实现对独立二进制.resourc...

    蒋金楠
  • 体验Django REST framework,解读REST架构风格

    写下这篇文章,一方面记录Django REST framework的体验过程,同时借此解读下REST架构风格。

    Coder Sam
  • Nginx采用https加密访问后出现的问题

    线上的一个网站运行了一段时间,应领导要求,将其访问方式更改为https加密方式。 更改为https后,网站访问正常,但网站注册功能不能正常使用了! 经过排查,是...

    洗尽了浮华

扫码关注云+社区

领取腾讯云代金券