Apache Dubbo的@SPI接口应用

记录:472

场景:使用Apache Dubbo的@SPI接口加载实现类搭建框架。

版本:JDK 1.8,dubbo-common-3.0.0。

SPI全称Service Provider Interface。

1.基础

1.1引用依赖

XML 复制代码
<dependency>
  <groupId>org.apache.dubbo</groupId>
  <artifactId>dubbo-common</artifactId>
  <version>3.0.0</version>
</dependency>

1.2应用

(1)使用@SPI注解作用在自定义接口com.hub.example.pf.adapter.IPfDataAdapter。

(2)业务类TCityAdapterImpl、TProvinceAdapterImpl等实现接口IPfDataAdapter。

(3)在..\src\main\resources目录下,新建\META-INF\services目录

(4)在\META-INF\services目录新建配置文件:com.hub.example.pf.adapter.IPfDataAdapter,文件名称就是@SPI注解作用的接口全路径名称。

(5)在\META-INF\services\com.hub.example.pf.adapter.IPfDataAdapter配置文件中添加入下内容(key=value键值对):

XML 复制代码
t_province=com.hub.example.process.adapter.TProvinceAdapterImpl
t_city=com.hub.example.process.adapter.TCityAdapterImpl

(6)根据配置文件中key名称和接口名称获取实现类,如下:

java 复制代码
IPfDataAdapter var= ExtensionLoader.getExtensionLoader(IPfDataAdapter.class).getExtension(tableName);

1.3逻辑

Apache Dubbo框架对使用@SPI注解接口,会在..\src\main\resources\META-INF\services目录下扫描配置并加载。

2.示例场景

(1)从某数据源(比如数据库)中读取数据存放在:Map<String, Object> data。

(2)组装成Tuple3<String, String, Map<String, Object>> in数据格式,其中Tuple3第一个参数数:表名称,第二参数:指定的字段名称,第三个参数就是数据。

(3)使用计算框架com.hub.example.pf.function.PfDataMapFunction计算业务

输入:Tuple3<String, String, Map<String, Object>> in;

输出:Tuple3<String, String, Map<String, String>> out;

(4)把Tuple3<String, String, Map<String, String>> out传递给下游处理。比如数据写入到HBase等目的端。

3.示例代码

3.1接口和抽象类

(1)接口 IPfDataAdapter

全称:com.hub.example.pf.adapter.IPfDataAdapter

代码:

java 复制代码
@SPI
public interface IPfDataAdapter {
    Tuple3<String, String, Map<String, String>> getPfData(Map<String, Object> value);
}

(2)抽象类

全称:com.hub.example.pf.adapter.PfDataAdapterAbstract

代码:

java 复制代码
public abstract class PfDataAdapterAbstract implements IPfDataAdapter {
    public PfDataAdapterAbstract() {
    }
    public Tuple3<String, String, Map<String, String>> getPfData(Map<String, Object> data) {
        try {
            Map<String, String> result = new HashMap(data.size());
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                if (entry.getValue() != null) {
                    result.put(entry.getKey(), entry.getValue().toString());
                }
            }
            return new Tuple3(this.getTableName(), this.getRowKeyColumns(), result);
        } catch (Exception e) {
            return new Tuple3(null, null, new HashMap<>());
        }
    }
    public abstract String getDataType();
    public String getTableName() {
        return TableConfig.getTableName(this.getDataType());
    }
    public String getRowKeyColumns() {
        return TableConfig.getRowKeyColumns(this.getDataType());
    }
}

3.2计算框架

全称:com.hub.example.pf.function.PfDataMapFunction

代码:

java 复制代码
public class PfDataMapFunction {
    public PfDataMapFunction() {
    }
    public Tuple3<String, String, Map<String, String>> map(Tuple3<String, String, Map<String, Object>> data) {
        try {
            String tableName = (String) data.f0;
            IPfDataAdapter dataAdapter = ExtensionLoader.getExtensionLoader(IPfDataAdapter.class).getExtension(tableName);
            if (dataAdapter == null) {
                return new Tuple3();
            } else {
                return dataAdapter.getPfData((Map) data.f2);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Tuple3();
        }
    }
}

3.3业务类

(1)业务类TProvinceAdapterImpl对应表:t_province

全称:com.hub.example.process.adapter.TProvinceAdapterImpl

代码:

java 复制代码
public class TProvinceAdapterImpl extends PfDataAdapterAbstract {
    public TProvinceAdapterImpl() {
    }
    @Override
    public String getDataType() {
        return "T_PROVINCE";
    }
    public Tuple3<String, String, Map<String, String>> getPfData(Map<String, Object> data) {
        if (data.get("PROVINCE_ID") == null) {
            return new Tuple3();
        }
        return super.getPfData(data);
    }
}

(2)业务类TCityAdapterImpl对应表:t_city

全称:com.hub.example.process.adapter.TCityAdapterImpl

代码:

java 复制代码
public class TCityAdapterImpl extends PfDataAdapterAbstract {
    @Override
    public String getDataType() {
        return "T_CITY";
    }

    public Tuple3<String, String, Map<String, String>> getPfData(Map<String, Object> data) {
        if (data.get("CITY_ID") == null) {
            return new Tuple3();
        }
        return super.getPfData(data);
    }
}

3.4配置文件

(1)配置目录..\META-INF\services

目录:..\src\main\resources\META-INF\services

(2)配置文件com.hub.example.pf.adapter.IPfDataAdapter

文件名:com.hub.example.pf.adapter.IPfDataAdapter

文件内容:

java 复制代码
t_province=com.hub.example.process.adapter.TProvinceAdapterImpl
t_city=com.hub.example.process.adapter.TCityAdapterImpl

3.5配置类

全称:com.hub.example.config.TableConfig

代码:

java 复制代码
public class TableConfig {
    private static ConcurrentHashMap<String, String> tableConfig = new ConcurrentHashMap<>();
    static {
        tableConfig.put("TABLE:T_PROVINCE", "HUB:T_PROVINCE");
        tableConfig.put("ROW_KEY:T_PROVINCE", "V_DATA_DATE,PROVINCE_ID");
        tableConfig.put("TABLE:T_CITY", "HUB:T_CITY");
        tableConfig.put("ROW_KEY:T_CITY", "V_DATA_DATE,CITY_ID");
    }
    public static String getTableName(String tableName) {
        return tableConfig.get("TABLE:" + tableName.toUpperCase());
    }
    public static String getRowKeyColumns(String tableName) {
        return tableConfig.get("ROW_KEY:" + tableName.toUpperCase());
    }
}

3.6实体类

全称:com.hub.example.api.Tuple3

代码:

java 复制代码
public class Tuple3<T0, T1, T2> implements Serializable {
    private static final long serialVersionUID = 1L;
    public T0 f0;
    public T1 f1;
    public T2 f2;

    public Tuple3() {
    }

    public Tuple3(T0 f0, T1 f1, T2 f2) {
        this.f0 = f0;
        this.f1 = f1;
        this.f2 = f2;
    }

    public static String arrayAwareToString(Object o) {
        String arrayString = Arrays.deepToString(new Object[]{o});
        return arrayString.substring(1, arrayString.length() - 1);
    }

    public String toString() {
        return "(" + arrayAwareToString(this.f0) + ";" + arrayAwareToString(this.f1) + ";" + arrayAwareToString(this.f2) + ")";
    }
}

4.示例测试

全称:com.hub.example.process.ExampleApplicationSPI

代码:

java 复制代码
public class ExampleApplicationSPI {
    public static void main(String[] args) throws Exception {
        PfDataMapFunction dataPfMapFunction = new PfDataMapFunction();
        //操作t_province
        String table01 = "t_province";
        Map<String, Object> data01 = getTProvince();
        Tuple3<String, String, Map<String, Object>> in01 = new Tuple3(table01, data01.get("PROVINCE_ID"), data01);
        Tuple3<String, String, Map<String, String>> out01 = dataPfMapFunction.map(in01);
        System.out.println("操作表t_province后数据: " + out01.toString());
        //操作t_city
        String table02 = "t_city";
        Map<String, Object> data02 = getTCity();
        Tuple3<String, String, Map<String, Object>> in02 = new Tuple3(table02, data02.get("CITY_ID"), data02);
        Tuple3<String, String, Map<String, String>> out02 = dataPfMapFunction.map(in02);
        System.out.println("操作表t_city后数据: " + out02.toString());
    }
    public static Map<String, Object> getTProvince() {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("PROVINCE_ID", 33001694333578181L);
        dataMap.put("V_DATA_DATE", "20230910");
        dataMap.put("PROVINCE_NAME", "浙江");
        dataMap.put("GROSS", 7.77D);
        return dataMap;
    }
    public static Map<String, Object> getTCity() {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("CITY_ID", 33011694333578181L);
        dataMap.put("V_DATA_DATE", "20230911");
        dataMap.put("CITY_NAME", "杭州");
        dataMap.put("GROSS", 1.88D);
        return dataMap;
    }
}

以上,感谢。

2023年9月10日

相关推荐
带刺的坐椅8 天前
Spring SPI、Solon SPI 有点儿像(Maven 与 Gradle)
java·spring·solon·spi
你好 贝弗利1 个月前
4.SPI外设—LCD小案例
stm32·单片机·lcd·spi
小嵌同学2 个月前
SPI驱动学习六(SPI_Master驱动程序)
linux·驱动开发·学习·嵌入式·c·spi
水w2 个月前
什么是java的spi?
java·spi
Dexu73 个月前
【ConcurrentHashMap】JDK1.7版本源码解读与分析
hashmap·jdk1.8·jdk1.7
码农研究僧3 个月前
详细分析Java中的SPI机制(附Demo)
java·服务发现·反射·spi·动态加载
weiwei228443 个月前
STM32F103 SPI详解及示例代码
stm32·嵌入式·spi
mx_jun5 个月前
通讯协议大全(UART,RS485,SPI,IIC)
单片机·嵌入式硬件·uart·iic·通讯协议·spi·rs485
PegasusYu5 个月前
STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX
stm32·文件操作·flash·w25q·spi·模拟u盘·fats
常驻客栈5 个月前
A48 STM32_HAL库函数 之 SPI通用驱动 -- B -- 所有函数的介绍及使用
stm32·单片机·嵌入式硬件·hal库·spi·常驻客栈·hal库函数介绍