该文章内容发布已经超过一年,请注意检查文章中内容是否过时。
在上一章中我们初始化应用模型对象的时候,了解到有几个地方用到了扩展机制来创建对象,这一章我们会详细来讲一下这个扩展对象的加载过程,这里我们先来回顾下哪些地方用到了扩展机制:
有了以上的应用场景我们可以来看下扩展机制了
为什么要用到扩展这个想必每个编程人员都比较了解,一个好的程序是要遵循一定的设计规范比如设计模式中的开闭原则 英文全称是 Open Closed Principle,简写为 OCP,对扩展开放、对修改关闭:
对扩展开放: 指的是我们系统中的模块、类、方法对它们的提供者(开发者)应该是开放的,提供者可以对系统进行扩展(新增)新的功能。
对修改关闭: 指的是系统中的模块、类、方法对它们的使用者(调用者)应该是关闭的。使用者使用这些功能时,不会因为提供方新增了功能而导致使用者也进行相应修改。
我们再来了解下Dubbo的一些基本特性: 下面这句话是我摘自官网的: Apache Dubbo 是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力。这意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通信能力, 同时利用 Dubbo 提供的丰富服务治理能力,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。同时 Dubbo 是高度可扩展的,用户几乎可以在任意功能点去定制自己的实现,以改变框架的默认行为来满足自己的业务需求。 Dubbo3 基于 Dubbo2 演进而来,在保持原有核心功能特性的同时, Dubbo3 在易用性、超大规模微服务实践、云原生基础设施适配、安全设计等几大方向上进行了全面升级。 以下文档都将基于 Dubbo3 展开。
对修改关闭的地方: 对于Apache Dubbo来说 不变的是RPC调用流程,微服务治理这些抽象的概念,我们可以用摘自官网的下面几个图表示:
再来看一个调用链路的架构图
对扩展开放: : 对于Apache Dubbo来说 变化的是RPC调用流程和微服务治理这些抽象的概念的具体实现,每个点应该用什么技术实现,又是用什么场景,这个可以用如下图来表示下:
看到这里 应该各位就明白了,我们写程序是为了业务,而针对不同的业务需求很多场景下我们是需要使用不同的实现来满足的,Dubbo使用微内核的架构,将具体的实现开放出来,让使用者可以根据自己的需求来选择,定制. Dubbo开放了很多的扩展点供大家扩展,可想而知使用Dubbo的灵活性是非常高的。
微内核架构: 微内核架构由两大架构模块组成:核心系统与插件模块,设计一个微内核体系关键工作全部集中于核心系统怎么构建。 核心系统 : 负责和具体业务功能无关的通用功能,例如模块加载、模块间通信等,这个其实对应着Dubbo的SPI机制。 插件模块 : 负责实现具体的业务逻辑,Dubbo,SPI接口与实现。
前面我们说了为什么要使用扩展机制,这里我们来看下具体实现
先将扩展包里面的代码截个图认识认识各类型的单词
顺便我们先简单看下类结构图,后续再详细看每个类型的解释:
为了后续看具体的扩展加载流程我们先看下以上类型的解释说明:
ExtensionAccessor
ExtensionDirector
ExtensionScope
ExtensionLoader
ExtensionPostProcessor
LoadingStrategy
DubboInternalLoadingStrategy
DubboLoadingStrategy
ServicesLoadingStrategy
Wrapper注解
SPI注解
ExtensionInjector接口
ExtensionAccessorAware
DisableInject注解
AdaptiveClassCodeGenerator
Adaptive注解
为ExtensionLoader注入依赖扩展实例提供有用信息。
Activate注解
ActivateComparator
MultiInstanceActivateComparator
WrapperComparator
AdaptiveExtensionInjector
SpiExtensionInjector
了解了这么多与扩展相关的概念,接下来我们就来从前面的代码调用中找几个例子来看下扩展的调用过程:
代码来源于FrameworkModel对象的初始化initialize()中的如下代码调用:
TypeDefinitionBuilder中初始化类型构建器代码如下:
以上扩展调用的时候对于扩展加载器对象的获取代码如下所示,我们来看下它的调用链路
getExtensionLoader方法来源于FrameworkModel类型的父类型ScopeModel的实现的接口ExtensionAccessor中的默认方法(JDK8 默认方法)
ExtensionAccessor接口中的getExtensionLoader方法如下代码:
获取扩展加载器之前需要先获取扩展访问器: 这里的链路先梳理下:
模型对象(FrameworkModel)-–> 扩展访问器(ExtensionAccessor) —> 作用域扩展加载程序管理器(ExtensionDirector) —>
这个getExtensionDirector()方法来源于FrameworkModel的抽象父类型ScopeModel中的getExtensionDirector()如下代码:
这里直接返回了extensionDirector,,不知道介绍到这里记得这个扩展加载程序管理器extensionDirector对象的由来不, 在上个章节《3-框架,应用程序,模块领域模型Model对象的初始化》中3.2.2 初始化ScopeModel的章节中的ScopeModel类型的初始化方法initialize()方法中我们提到过这个对象的创建,具体代码如下所示(这个代码比较简单):
我们继续前面getExtensionLoader(type)方法调用逻辑,前面我们知道了这个扩展访问器的对象是ExtensionDirector,接下来我们看下ExtensionDirector中获取扩展加载器的代码(如下所示): 在详细介绍扩展加载器对象获取之前我们先来看下当前我们要加载的扩展类型的源码,后续会用到: 我们要加载的扩展类型TypeBuilder接口
ExtensionDirector类型中获取扩展加载器的代码 这个代码非常有意思 其实就是前面说到的域模型架构的数据访问架构类似于JVM类加载器访问加载类的情况,但是这个顺序可能有所不同,Dubbo的扩展加载器是如何访问的呢? 遵循以下顺序:
前面提到的withExtensionAnnotation判断代码如下:
ExtensionDirector类型的createExtensionLoader方法
ExtensionDirector类型的createExtensionLoader0方法
扩展加载器相对来说是比较复杂的实现内容比较多,用到哪里我们说下哪里,这里先来看ExtensionLoader的构造器代码如下所示:
先来看 创建实例化对象的策略对象代码 initInstantiationStrategy();
再来看ExtensionInjector扩展对象的获取
原文: «Dubbo的扩展机制»