摘要:对于开发者来说,无疑是最常用也是最基础的框架之一。概念上的东西还是要提一嘴的用容器来管理。和是容器的两种表现形式。定义了简单容器的基本功能。抽象出一个资源类来表示资源调用了忽略指定接口的自动装配功能委托解析资源。
对于Java开发者来说,Spring无疑是最常用也是最基础的框架之一。(此处省略1w字吹Spring)。相信很多同行跟我一样,只是停留在会用的阶段,比如用@Component写一个组件、用@Autowired注入其他组件等等,但是不知道为什么可以这么做,Spring是怎么实现的。为了了解这些,我阅读了《Spring源码深度解析》,这本书讲的很详细,但是因为步骤多而复杂容易记混,我就做了一下梳理,先呈现大致流程,但对每个步骤进行详细描述。
概念上的东西还是要提一嘴的:
Spring用IoC容器来管理Bean。
BeanFactory和ApplicationContext是SpringIoC容器的两种表现形式。
BeanFactory定义了简单IoC容器的基本功能。
ApplicationContext实现了BeanFactory,且通过继承MessageSource、ResourceLoader、ApplicationEventPublisher接口,添加了许多高级容器的特性。
这里以XmlBeanFactory为代表,看容器是怎么工作的。
新建一个XmlBeanFactory很简单,只需要你有一个符合格式的xml文件,里面用
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("test.xml"))
新建了一个ClassPathResource资源对象作为参数传入XmlBeanFactory的构造函数。
点进XmlBeanFactory类,XmlBeanFactory会先调用父类构造器,一直跟踪到AbstractAutowireCapableBeanFactory,会看到调用了三次ignoreDependencyInterface用来忽略给定接口的自动装配功能(后面会提到);再调用this.reader.loadBeanDefinitions(Resource),用自己持有的XmlBeanDefinitionReader解析传入的资源。所以最宏观的三个步骤:
1、新建了一个ClassPathResource资源。抽象出一个资源类来表示资源;
2、调用了ignoreDependencyInterface忽略指定接口的自动装配功能;
3、委托XmlBeanDefinitionReader解析资源。
重点肯定在第三步了,点进XmlBeanDefinitionReader,到loadBeanDefinitions(EncodedResource),先从
Resource获取InputStream构造成InputSource,作为参数调用doLoadBeanDefinitions(InputSource, Resource)开始真正的解析。所以第三步下面是两个小步骤:
3.1、从Resource获取输入流;
3.2、调用doLoadBeanDefinitions继续解析。
再看doLoadBeanDefinitions方法,主要是两个方法,doLoadDocument(inputSource, resource)解析输入流返回一个Document对象;registerBeanDefinitions(doc, resource)继续解析Document返回解析的Bean数量,所以3.2下面是两个步骤:
3.2.1、将资源解析成Document对象(这个步骤这边就不展开了,有兴自究);
3.2.2、解析Document,提取注册Bean。
来到registerBeanDefinitions方法,这里创建了一个BeanDefinitionDocumentReader对象负责具体解析(是不是觉得又冒出了不认识的类,框架就是这样,遵循单一职责的原则,把一个集中的逻辑放到其他类中处理),它调用doRegisterBeanDefinitions(doc.getDocumentElement()),提取Document的root作为参数继续解析,先查找解析profile属性,将表示环境的属性注册到Environment;然后遍历root每个子节点,如果是默认标签,调用parseDefaultElement进行解析;如果是自定义标签,就调用delegate.parseCustomElement。所以3.2.2下面是这几个步骤:
3.2.2.1、创建BeanDefinitionDocumentReader委托解析对象;
3.2.2.2、解析profile属性到Environment;
3.2.2.3、遍历子节点,继续解析默认标签和自定义标签。
我们这边主要分析默认标签的解析,自定义的有兴自究。首先根据标签类型选择不同的处理方法,类型分别是import、alias、bean和beans。重点肯定是对bean标签的解析,进入processBeanDefinition方法,我们看到里面先委托BeanDefinitionParserDelegate解析出一个持有bean信息的BeanDefinitionHolder;如果BeanDefinitionHolder不为空且子节点下存在自定义标签,再解析它们;然后对解析完成后的BeanDefinitionHolder进行注册,注册过程很简单就是将BeanDefinitionHolder持有的beanName和BeanDefinition的键值对、beanName和每个alias别名的键值对保存在容器中;最后发出bean已注册完成的事件通知,所以这里分为4步:
3.2.2.3.1、委托BeanDefinitionParserDelegate解析返回BeanDefinitionHolder;
3.2.2.3.2、解析存在的自定义标签;
3.2.2.3.3、解析完成后注册;
3.2.2.3.4、发出响应事件。
到了这里终于开始具体的解析,过程其实就是先解析出beanName、alias别名,然后把其余各种标签,如class、scope、lazy-init等属性解析成用于属性承载的BeanDefinition对象的成员变量,最后将beanName、alias数组和BeanDefinition封装成BeanDefinitionHolder对象返回。具体各种属性的功能和规则这边就不展开了,有兴自究。
对于import、alias和beans标签,简述一下:alias的解析和bean中的alias解析差不多,也是将每一个别名与beanName以map形式保存;impot可以导入其他配置文件,解析过程就是找到那个文件然后递归进行解析;beans就是把多个bean标签包起来,然后遍历解析每一个bean标签。
画一个流程图作为总结:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/72507.html
摘要:本文是容器源码分析系列文章的第一篇文章,将会着重介绍的一些使用方法和特性,为后续的源码分析文章做铺垫。我们可以通过这两个别名获取到这个实例,比如下面的测试代码测试结果如下本小节,我们来了解一下这个特性。 1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本。经过十几年的迭代,现在的 Spring 框架已经非常成熟了...
摘要:依赖注入是向某个类或方法注入一个值,其中所用到的原理就是控制反转。但发现更多时间是在调和的源码。里面就是从中取出这个,完成控制反转的。控制反转的优点最后来以我个人观点谈谈控制反转的优点吧。控制反转为了降低项目耦合,提高延伸性。 本章开始来学习下Spring的源码,看看Spring框架最核心、最常用的功能是怎么实现的。网上介绍Spring,说源码的文章,大多数都是生搬硬推,都是直接看来的...
摘要:实例化时,发现又依赖于。一些缓存的介绍在进行源码分析前,我们先来看一组缓存的定义。可是看完源码后,我们似乎仍然不知道这些源码是如何解决循环依赖问题的。 1. 简介 本文,我们来看一下 Spring 是如何解决循环依赖问题的。在本篇文章中,我会首先向大家介绍一下什么是循环依赖。然后,进入源码分析阶段。为了更好的说明 Spring 解决循环依赖的办法,我将会从获取 bean 的方法getB...
摘要:在写完容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了天时间阅读了方面的源码。从今天开始,我将对部分的源码分析系列文章进行更新。全称是,即面向切面的编程,是一种开发理念。在中,切面只是一个概念,并没有一个具体的接口或类与此对应。 1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解。在写完 Spring IOC 容器源码分析系列...
摘要:简介为了写容器源码分析系列的文章,我特地写了一篇容器的导读文章。在做完必要的准备工作后,从本文开始,正式开始进入源码分析的阶段。从缓存中获取单例。返回以上就是和两个方法的分析。 1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章。在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一些建议。在...
阅读 2770·2021-11-22 14:44
阅读 506·2021-11-22 12:00
阅读 3644·2019-08-30 15:54
阅读 1528·2019-08-29 17:15
阅读 1859·2019-08-29 13:50
阅读 1071·2019-08-29 13:17
阅读 3481·2019-08-29 13:05
阅读 1157·2019-08-29 11:31