RPC-java/version6/krpc-common/src/main/java/common/spi/SpiLoader.java
2025-02-13 16:39:06 +08:00

112 lines
4.0 KiB
Java

package common.spi;
import cn.hutool.core.io.resource.ResourceUtil;
import common.serializer.myserializer.Serializer;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @ClassName SpiLoader
* @Description spi实现
* @Author Tong
* @LastChangeDate 2024-12-05 14:53
* @Version v5.0
*/
@Slf4j
public class SpiLoader {
// 存储已加载的 SPI 实现类的映射
private static final Map<String, Map<String, Class<? extends Serializer>>> loadedSpiMap = new ConcurrentHashMap<>();
// 缓存实例,避免重复实例化
private static final Map<String, Object> instanceCache = new ConcurrentHashMap<>();
// SPI 配置文件的路径
private static final String SPI_CONFIG_DIR = "META-INF/serializer/";
/**
* 加载指定接口的 SPI 实现类
*
* @param serviceInterface 接口类
*/
public static void loadSpi(Class<?> serviceInterface) {
String interfaceName = serviceInterface.getName();
// 如果已经加载过该接口的 SPI 实现,直接返回
if (loadedSpiMap.containsKey(interfaceName)) {
return;
}
Map<String, Class<? extends Serializer>> keyClassMap = new HashMap<>();
// 读取配置文件,获取所有实现类
List<URL> resources = ResourceUtil.getResources(SPI_CONFIG_DIR + serviceInterface.getName());
for (URL resource : resources) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream()))) {
String line;
while ((line = reader.readLine()) != null) {
if (!line.trim().isEmpty() && !line.startsWith("#")) {
String[] parts = line.split("=");
if (parts.length == 2) {
String key = parts[0].trim();
String className = parts[1].trim();
Class<?> implClass = Class.forName(className);
if (serviceInterface.isAssignableFrom(implClass)) {
keyClassMap.put(key, (Class<? extends Serializer>) implClass);
}
}
}
}
} catch (IOException | ClassNotFoundException e) {
log.error("Failed to load SPI resource: " + resource, e);
}
}
// 将该接口的 SPI 实现类存入缓存
loadedSpiMap.put(interfaceName, keyClassMap);
}
/**
* 根据接口和 key 获取 SPI 实现类实例
*
* @param serviceInterface 接口类
* @param key 序列化器的 key
* @param <T> 接口类型
* @return 对应的 SPI 实现类实例
*/
public static <T> T getInstance(Class<T> serviceInterface, String key) {
String interfaceName = serviceInterface.getName();
Map<String, Class<? extends Serializer>> keyClassMap = loadedSpiMap.get(interfaceName);
if (keyClassMap == null) {
throw new RuntimeException("SPI not loaded for " + interfaceName);
}
Class<? extends Serializer> implClass = keyClassMap.get(key);
if (implClass == null) {
throw new RuntimeException("No SPI implementation found for key " + key);
}
// 从缓存中获取实例,如果不存在则创建
String implClassName = implClass.getName();
if (!instanceCache.containsKey(implClassName)) {
try {
instanceCache.put(implClassName, implClass.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("Failed to instantiate SPI implementation: " + implClassName, e);
}
}
return (T) instanceCache.get(implClassName);
}
}