dubbo源码分析3——SPI机制中的ExtensionLoader类的objectFactory属性分析
ExtensionLoader类是整个SPI的核心类,每个SPI都会对应一个ExtensionLoader类实例,这个类的构造方法如下:
private ExtensionLoader(Class<?> type) {
        this.type = type;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }
里面的objectFactory对应的就是ExtensionFactory类的实例,通过源码能发现,ExtensionFactory自身也是一个SPI接口,那么它也会有一个对应的ExtensionLoader类实例,这个类实例中的objectFactory属性为null ,而其他的ExtensionLoader类实例中的 objectFactory属性是 : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()
我们就先来分析下ExtensionLoader.getExtensionLoader(ExtensionFactory.class) 这句代码。
// 先通过type从缓存中获取ExtensionLoader,如果缓存中不存在,则创建相应的ExtensionLoader放入缓存,再返回
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
if (type == null)
throw new IllegalArgumentException("Extension type == null");
if(!type.isInterface()) {
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
}
if(!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type(" + type +
") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
} ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) {
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
getAdaptiveExtension()内部的调用过程如下(注意这是一个实例方法):
-> if(cachedAdaptiveInstance.get() == null){ createAdaptiveExtension() }
->getAdaptiveExtensionClass() //下面的调用有两个分支
// 分支1
		       ->getExtensionClasses()
		   	       ->loadExtensionClasses()
		   	           ->loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
injectExtension //完成注入,这是 ExtensionFactory 类的作用之所在
// 分支2
->createAdaptiveExtensionClass()
injectExtension
经过上述分析,可以得出 ExtensionLoader.getExtensionLoader(ExtensionFactory.class) 返回的是 com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory类的实例,这个类在ExtensionFactory的SPI描述文件中的第二行
spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
AdaptiveExtensionFactory的源码如下
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory { private final List<ExtensionFactory> factories; public AdaptiveExtensionFactory() {
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
for (String name : loader.getSupportedExtensions()) {
list.add(loader.getExtension(name));
}
factories = Collections.unmodifiableList(list);
} public <T> T getExtension(Class<T> type, String name) {
for (ExtensionFactory factory : factories) {
T extension = factory.getExtension(type, name);
if (extension != null) {
return extension;
}
}
return null;
} }
总结:
通过上述分析,可以知道:
1. 除了ExtensionFactory之外,其他的SPI接口对应的ExtensionLoader类实例中的 objectFactory属性都是AdaptiveExtensionFactory的实例对象。
2. 且这些AdaptiveExtensionFaatory实例都是同一个,这是因为ExtensionLoader的类属性会会在EXTENSION_LOADERS中缓存创建好的loader,每个loader又会在其的实例属性cachedAdaptiveClass缓存这个adaptive性质的Extension类。
3. ExtensionLoader的injectExtension方法完成的注入工作正是objectFactory(ExtensionFactory类)的真正作用。这个作用留待下一篇再做分析。
dubbo源码分析3——SPI机制中的ExtensionLoader类的objectFactory属性分析的更多相关文章
- dubbo源码分析2——SPI机制中的SPI实现类的读取和预处理
		
SPI机制中的SPI实现类的读取和预处理是由ExtensionLoader类的loadFile方法来完成的 loadFile方法的作用是读取dubbo的某个SPI接口的spi描述文件,然后进行缓存,缓 ...
 - Dubbo源码解析之SPI(一):扩展类的加载过程
		
Dubbo是一款开源的.高性能且轻量级的Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用.智能容错和负载均衡,以及服务自动注册和发现. Dubbo最早是阿里公司内部的RPC框架,于 ...
 - dubbo源码分析6——SPI机制中的AOP
		
在 ExtensionLoader 类的loadFile方法中有下图的这段代码: 类如现在这个ExtensionLoader中的type 是Protocol.class,也就是SPI接口的实现类中Xx ...
 - Dubbo源码学习之-SPI介绍
		
前言 学习之路还是要戒骄戒躁,一以贯之的积累前行.之前的公司部门技术达人少,自己总向往那些技术牛人多的团队,想象自己进去之后能跟别人学到多少东西.如今进到一个这样的团队之后,却发现之前自己的想法过于幼 ...
 - dubbo源码阅读之SPI
		
dubbo SPI SPI,全程Service Provider interface, java中的一种借口扩展机制,将借口的实现类注明在配置文件中,程序在运行时通过扫描这些配置文件从而获取全部的实现 ...
 - 读Dubbo源码,学习SPI
		
核心类 ExtensionLoader 使用方法 定义接口,使用@SPI标记 @SPI("impl1") public interface SimpleExt { // @Adap ...
 - Dubbo 源码分析 - SPI 机制
		
1.简介 SPI 全称为 Service Provider Interface,是 Java 提供的一种服务发现机制.SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加 ...
 - dubbo源码分析4——SPI机制_ExtensionFactory类的作用
		
ExtensionFactory的源码: @SPI public interface ExtensionFactory { /** * Get extension. * * @param type o ...
 - Dubbo源码分析之 SPI(一)
		
一.概述 dubbo SPI 在dubbo的作用是基础性的,要想分析研究dubbo的实现原理.dubbo源码,都绕不过 dubbo SPI,掌握dubbo SPI 是征服dubbo的必经之路. 本篇文 ...
 
随机推荐
- Shell命令的执行顺序
			
shell执行命令的步骤顺序如上图,看起来有些复杂. 当命令行被处理时,每一个步骤都是在Shell的内存里发生的;Shell不会真的把每个步骤的发生显示给你看. 所以,你可以假想这事我们偷窥Shell ...
 - rancher使用fluentd-pilot收集日志分享
			
fluentd-pilot简介 fluentd-pilot是阿里开源的docker日志收集工具,Github项目地址:https://github.com/AliyunContainerService ...
 - springboot打包成war,部署到tomcat无法访问的问题
			
如题:实在是太坑.平时本地测试觉得很方便,但是到了项目打包发布掉链子了. 如很多帖子一样: 首先springboot内嵌的tomcat,再依赖servlet-api,修改启动类继承SpringBoot ...
 - mysql根据出生日期查询年龄
			
如题,根据出生日期查找计算出年龄,网上找了一大堆,数据库可以用,但是集成到mybatis它不答应了,报错.具体是大于号,小于号的问题.要我解决那个错误吗?不存在的.换一种方式就好了.而且sql语句一大 ...
 - 【leetcode70】【动态规划】 爬楼梯
			
(1 pass 一维动态规划) 爬楼梯(easy) 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数 ...
 - python实现双向链表
			
双向链表 一种更复杂的链表是“双向链表”或“双面链表”.每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值:而另一个指向下一个节点,当此节点为最后一个节点时,指向空值. 实现 c ...
 - Creating A Moddable Unity Game
			
前言: 对游戏进行修改与拓展(MOD)是我一直以来感兴趣的东西,我的程序生涯,也是因为在初中接触到GBA口袋妖怪改版开始的,改过也研究过一些游戏的MOD实现方式,早就想在自己的游戏中实现“MOD系统” ...
 - JSON CSRF新姿势
			
以前做渗透测试,遇到过很多次POST数据为JSON数据的CSRF,一直没有搞定,最近发现一个新姿势, 本文作者:Mannix@安全文库 微信公众号:安全文库 测试的时候,当应用程序验证了Cont ...
 - MySQL api
			
今天看去年年中写的代码,留意到一个关键时刻能提高效率的api:on duplicate key update: 语法: INSERT INTO INSERT INTO g_iot_user_build ...
 - UIScrollView嵌套的完美解决方案
			
UIScrollView嵌套的完美解决方案 做iOS开发,不可避免的会遇到UIScrollView的嵌套问题,之前也曾遇到过,吭哧吭哧做完了,效果不理想,和产品大战好几回合,就那样了.不可避免的,又一 ...