Struct Util 权威指南 - 通过 SPI 实现自定义扩展

524 字
3 分钟
Struct Util 权威指南 - 通过 SPI 实现自定义扩展

Struct Util 是一个 Java 语言开发的结构化数据映射处理工具。Struct Util 主要解决两个方面的问题。第一个方面将*.xls, *.csv 等配置友好型数据源转换为业务侧友好型的 bean 结构,对配置数据和使用数据进行解耦,让开发和运营、策划三方实现共赢。第二方面解决了数据表热重载,数据有条件过滤,表结构跨表引用等等应用相关的问题。

StructUtil是博主个人作品, 稍微有自吹自擂的嫌疑, 欢迎:star:收藏。哈哈, 因为是个人作品,应该是足够”权威”了。嘻嘻~~

SPI 扩展#

Struct Util 提供了 Converters, Converter, StructFactoryBean, StructHandler四个扩展点,允许用户进行功能扩展。

EnhancedServiceLoader#

相比于 JDK 内置的 SPI 功能解决了加载异常处理,懒加载等问题。核心加载代码如下:

void handleDefinitionFile(String dir, ClassLoader classLoader, List<ExtensionDefinition> output) throws IOException {
String fileName = dir + this.service.getName();
Enumeration<URL> urls = classLoader != null
? classLoader.getResources(fileName)
: ClassLoader.getSystemResources(fileName);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) {
String line = null;
while (null != (line = reader.readLine())) {
line = line.trim();
if (line.length() > 0) {
try {
output.add(this.createExtensionDefinition(line, classLoader));
} catch (LinkageError | ClassNotFoundException e) {
LOGGER.warn("load [{}] class failure. {}", line, e.getMessage());
}
}
}
} catch (Throwable e) {
LOGGER.warn("handle extension definition file error.", e);
}
}
}
ExtensionDefinition createExtensionDefinition(String clzName, ClassLoader loader) throws ClassNotFoundException {
Class<?> clzOfService = Class.forName(clzName, true, loader);
String name = null;
int order = 0;
SPI anno = AnnotationUtils.findAnnotation(SPI.class, clzOfService);
if (anno != null) {
name = anno.name();
order = anno.order();
}
return new ExtensionDefinition(name, clzOfService, order);
}

自定义 Converter#

Struct Util内置了常用的类型转换器, 当用户有特殊转换需求时,可以通过扩展 Converter 接口实现转换业务,并通过 SPI 机制自动注册到系统中。以下是一个简单的字符串转数组的转换器实例。

public class StringToArrayConverter implements Converter {
@Override
public Object convert(Object originValue, Class<?> targetType) {
if (!targetType.isArray() || String.class != originValue.getClass()) {
return null;
}
String content = (String) originValue;
Class<?> componentType = targetType.getComponentType();
String[] data = content.split(separator);
if (exceptBlank) {
data = Arrays.stream(data)
.map(String::trim)
.filter(s -> !s.isEmpty())
.toArray(String[]::new);
}
Object array = Array.newInstance(componentType, data.length);
for (int i = 0; i < data.length; i++) {
Array.set(array, i, ConverterUtil.covert(data[i], componentType));
}
return array;
}
}

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
Struct Util 权威指南 - 通过 SPI 实现自定义扩展
https://tinyzzh.github.io/posts/2023-05-01-struct_util_04_spi_custom_extension/
作者
TinyZ Zzh
发布于
2023-05-01
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
TinyZ Zzh
专注于高并发服务器、网络游戏相关(Java、PHP、Unity3D、Unreal Engine等)技术,热爱游戏事业, 正在努力实现自我价值当中。
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
211
分类
38
标签
200
总字数
337,853
运行时长
0
最后活动
0 天前

文章目录