dubbo SPI机制
源码分析:
- /**
- * 获取扩展类
- */
- @SuppressWarnings("unchecked")
- public T getExtension(String name) {
- if (StringUtils.isEmpty(name)) {
- throw new IllegalArgumentException("Extension name == null");
- }
- // 获取默认的拓展实现类
- if ("true".equals(name)) {
- return getDefaultExtension();
- }
- // Holder用于持有目标对象
- final Holder<Object> holder = getOrCreateHolder(name);
- Object instance = holder.get();
- // 双重检查
- if (instance == null) {
- synchronized (holder) {
- instance = holder.get();
- if (instance == null) {
- // 创建拓展实例
- instance = createExtension(name);
- // 设置实例到 holder 中
- holder.set(instance);
- }
- }
- }
- return (T) instance;
- }
- // 创建拓展对象
- @SuppressWarnings("unchecked")
- private T createExtension(String name) {
- Class<?> clazz = getExtensionClasses().get(name);
- if (clazz == null) {
- throw findException(name);
- }
- try {
- T instance = (T) EXTENSION_INSTANCES.get(clazz);
- if (instance == null) {
- // 通过反射创建实例
- EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
- instance = (T) EXTENSION_INSTANCES.get(clazz);
- }
- // 向实例中注入依赖
- injectExtension(instance);
- Set<Class<?>> wrapperClasses = cachedWrapperClasses;
- if (CollectionUtils.isNotEmpty(wrapperClasses)) {
- // 循环创建 Wrapper 实例
- for (Class<?> wrapperClass : wrapperClasses) {
- // 将当前 instance 作为参数传给 Wrapper 的构造方法,并通过反射创建 Wrapper 实例。
- // 然后向 Wrapper 实例中注入依赖,最后将 Wrapper 实例再次赋值给 instance 变量
- instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
- }
- }
- return instance;
- } catch (Throwable t) {
- throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type
- + ") couldn't be instantiated: " + t.getMessage(), t);
- }
- }
- // 从配置文件中加载所有的拓展类,可得到“配置项名称”到“配置类”的映射关系表
- private Map<String, Class<?>> getExtensionClasses() {
- // 从缓存中获取已加载的拓展类
- Map<String, Class<?>> classes = cachedClasses.get();
- // 双重检查
- if (classes == null) {
- synchronized (cachedClasses) {
- classes = cachedClasses.get();
- if (classes == null) {
- // 加载拓展类
- classes = loadExtensionClasses();
- cachedClasses.set(classes);
- }
- }
- }
- return classes;
- }
- // synchronized in getExtensionClasses
- private Map<String, Class<?>> loadExtensionClasses() {
- cacheDefaultExtensionName();
- Map<String, Class<?>> extensionClasses = new HashMap<>();
- // 加载指定文件夹下的配置文件
- loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
- loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
- loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
- loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
- loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
- loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
- return extensionClasses;
- }
- private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type) {
- // fileName = 文件夹路径 + type 全限定名
- String fileName = dir + type;
- try {
- Enumeration<java.net.URL> urls;
- ClassLoader classLoader = findClassLoader();
- // 根据文件名加载所有的同名文件
- if (classLoader != null) {
- urls = classLoader.getResources(fileName);
- } else {
- urls = ClassLoader.getSystemResources(fileName);
- }
- if (urls != null) {
- while (urls.hasMoreElements()) {
- java.net.URL resourceURL = urls.nextElement();
- // 加载资源
- loadResource(extensionClasses, classLoader, resourceURL);
- }
- }
- } catch (Throwable t) {
- logger.error("Exception occurred when loading extension class (interface: " + type + ", description file: "
- + fileName + ").", t);
- }
- }
dubbo SPI机制的更多相关文章
- 【Dubbo源码阅读系列】之 Dubbo SPI 机制
最近抽空开始了 Dubbo 源码的阅读之旅,希望可以通过写文章的方式记录和分享自己对 Dubbo 的理解.如果在本文出现一些纰漏或者错误之处,也希望大家不吝指出. Dubbo SPI 介绍 Java ...
- Dubbo SPI 机制源码分析(基于2.7.7)
Dubbo SPI 机制涉及到 @SPI.@Adaptive.@Activate 三个注解,ExtensionLoader 作为 Dubbo SPI 机制的核心负责加载和管理扩展点及其实现.本文以 E ...
- Dubbo SPI机制之三Adaptive自适应功能
JDK标准中SPI机制的一个问题就是其一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源:扩展点加载失败,其他扩展点都用不了了.Dubbo是如何解决该问题动态的选 ...
- Dubbo SPI机制之一JDK中的SPI
首先简单阐述下什么是SPI:SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制.目前有不少框架用它来做服务的扩展发现,简单来说,就是一种动态 ...
- 面试常问的dubbo的spi机制到底是什么?
前言 dubbo是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力.作为spring cloud alibaba体系中重要的一部分,随着spring cloud alibaba在 ...
- SPI 机制-插件化扩展功能
SPI(Service Provider Interfaces),中文直译服务提供者接口,一种服务发现机制.可能很多人都不太熟悉这个机制,但是平常或多或少都用到了这个机制,比如我们使用 JDBC 连接 ...
- Dubbo SPI源码解析①
目录 0.Java SPI示例 1.Dubbo SPI示例 2.Dubbo SPI源码分析 SPI英文全称为Service Provider Interface.它的作用就是将接口实现类的全限定名 ...
- Dubbo 源码分析 - SPI 机制
1.简介 SPI 全称为 Service Provider Interface,是 Java 提供的一种服务发现机制.SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加 ...
- dubbo源码分析4——SPI机制_ExtensionFactory类的作用
ExtensionFactory的源码: @SPI public interface ExtensionFactory { /** * Get extension. * * @param type o ...
随机推荐
- eigenvalues problem
由于在看paper中经常会看到generalized eigenvalues.eigenvalues problem等字眼,今晚终于开始认真地重新看了一下线性代数中这部分内容.下面是在学习过程中找出来 ...
- harbor报错解决
1. [root@host-10-1-1-71 harbor]# docker login 10.1.1.71:5000Username (admin): Password: Error respon ...
- 关于img标签浏览器自带的边框,清除边框的解决方式(即img[src=""] img无路径情况下,灰色边框去除解决方法)
详解img[src=""] img无路径情况下,灰色边框去除解决方法 1.Js解决办法 <html> <head> <meta charset=&qu ...
- linux环境下安装yaf
一.ubuntu环境 1.首先到http://pecl.php.net/get/yaf下载最新版本的yaf,我的是yaf-2.2.9.tgz. 2.解压 tar -zxvf yaf-2.2.9.tgz ...
- jquery实现分页效果
通过jq实现分页的原理如下:将所有条数加载到页面中,根据每页放特定条数(例如 5 条)获取jquery对象索引,使部分条数显示,其他条数隐藏. 前提:引入jquery.js 代码 <!DOCTY ...
- Hand on Machine Learning 第三章:分类器
1. 获取数据 使用MNIST数据集练习分类任务 from sklearn.datasets import fetch_mldata from scipy.io import loadmat mnis ...
- css 命名 有的加# ,有的加点 ,有的没加。请问下都在什么情况下用的?
[nav{}]这样的样式是给特定的标签直接定义样式时使用的,这个样式名称是跟标签是相对应的,比如我要给<p></p>这个标签设置样式,那我就可以直接写:p{样式}就可以,但是这 ...
- 交换机安全学习笔记 第六章 IPV4 ARP攻击
ARP欺骗攻击 常用工具: dsniff(Linux/windows).ettercap(Linux/windows).cain(仅windows). ARP欺骗攻击的目的是嗅探发往某主机的所有IP ...
- oracle中的多表查询和子查询以及一些注意事项
多表查询就是使用两张表及其以上的查询.首先需要知道几个名词,笛卡尔积,内连接,外连接,子查询. 1)笛卡尔积 所谓笛卡尔积其实就是两张表数据的条数相乘得到的最后结果,例如表1有10条数据,表2有4条数 ...
- Vue.nextTick 的原理和用途
转载自https://segmentfault.com/a/1190000012861862 概览 官方文档说明: 用法: 在下次 DOM 更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法 ...