java实现插拔式加载用户自定义插件

 更新时间:2025年09月16日 10:13:40   作者:Java八股文  
本文主要介绍了DatalinkX通过自定义URLClassLoader实现插件化加载外部数据源jar包,突破SPI机制依赖限制,使用户无需修改源码即可扩展数据源同步功能,达成动态插拔效果

前言

从23年底开始维护自己的开源项目,异构数据源流转系统datalinkx,系统支持不同数据源之间的数据同步,包括mysql、oracle、es、redis等等。

有一天一个同学问我说datalinkx系统支不支持用户上传自己的自定义数据源插件,不用动datalinkx的源码即可让系统支持用户自定义数据源的读写同步呢。

我一听有点意思,一般我都是版本迭代后支持某个数据源的读写,能不能把这个能力开放出去呢,这样大家使用的时候就不需要等系统更新,上传符合规范的插件包就可以。

也就是说我们需要实现,用户只需要将其他数据源的同步jar包,放到某个文件夹下,系统就会自动扫描到这个jar包从而获得对应数据源的读写能力。

SPI

通常听到插件化就会下意识的想起SPI,SPI是JDK内置的一种类似服务提供发现的机制,比如java.sql.Driver接口,其他不同的数据源厂商可以针对这一接口做出不同的实现, MySQL和PostgreSQL分别有不同的实现提供给用户,利用SPI机制可以为某个接口寻找服务实现。

主要思想是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要,核心思想就解耦,具体实现可以参考jdbc的实现。

思考下利用SPI可以实现插拔式插件开发吗,似乎不可以,使用SPI必须在当前classpath中,也就是说虽然解耦了,但必须存在依赖,比如你想要让系统支持PG,必须要在项目中引入PG驱动依赖才可以加载到PG驱动内的相关类。

这样还是要修改系统源代码才能得到支持,这明显是不符合我们的预期的。

自定义加载器

我们想要的效果是用户可以开发一个独立的插件jar包,放到datalinkx的driver-dist目录下,datalinkx即可获得独立插件jar包中的能力。

看到这里有准备面试的jym心里默背一遍java类加载过程和双亲委派机制,背不下来的看完赶紧补上。我们知道一个JVM进程正常情况下只能加载当前classpath下的所有java类。

有没有通过扫描固定路径下的jar包,将外部java类加载当当前classpath的方式呢。有的兄弟,有的。

URLClassLoader

// 从driver-dist文件夹下读取各个数据源插件
List<URL> dataSourcePlugins = JarLoaderUtil.loadJarsFromDirectory(DRIVER_DIST);
String targetJarName = String.format("datalinkx-driver-%s-1.0.0.jar", dsType.toLowerCase());
String targetClassName = getDriverClass(dsType);

URL targetJarUrl = dataSourcePlugins.stream()
        .filter(plugin -> plugin.getPath().endsWith(targetJarName))
        .findFirst()
        .orElseThrow(() -> new DatalinkXServerException(StatusCode.DRIVER_LOAD_FAIL, "系统未支持该数据源类型"));

// 使用自定义的 URLClassLoader 加载目标 JAR 包中的类
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{targetJarUrl}, Thread.currentThread().getContextClassLoader());
Class<?> clazz = Class.forName(targetClassName, true, urlClassLoader);

我们总结一下具体做了啥:

  1. 各个数据源模块打包后都会自动复制到datalinkx/driver-dist中
  2. 通过使用自定义 URLClassLoader加载器加载driver-dist文件夹内的jar包
  3. 通过class.forName反射的方式生成对用对象

这样我们就可以在当前进程中加载到外部jar包中的类,也就实现了Java插拔式加载用户自定义插件功能。

到此这篇关于java实现插拔式加载用户自定义插件的文章就介绍到这了,更多相关java 插拔式加载自定义插件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • Java精品项目瑞吉外卖之员工新增篇

    Java精品项目瑞吉外卖之员工新增篇

    这篇文章主要为大家详细介绍了java精品项目-瑞吉外卖订餐系统,此项目过大,分为多章独立讲解,本篇内容为新增员工功能的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • SpringCloud使用集中配置组件Config规避信息泄露

    SpringCloud使用集中配置组件Config规避信息泄露

    项目应用中,数据库连接信息、Access-key、Secret-key等由于其及其敏感和特殊性,一旦泄露出去就很可能会使得应用遭到黑客攻击,例如数据库账号密码泄露可能导致“拖库”,甚至数据丢失。此等事件偶有发生,那么,在分布式微服务项目中,怎么避免这种情况呢
    2022-07-07
  • Java类变量和成员变量初始化过程的应用介绍

    Java类变量和成员变量初始化过程的应用介绍

    昨天看了一本叫做《突破程序员基本功的16课》的书,个人感觉还可以,主要对Java的技巧进行了一些深入的讲解,让我对类的初始化和对象的创建有了新的认识
    2013-04-04
  • Java中关于泛型、包装类及ArrayList的详细教程

    Java中关于泛型、包装类及ArrayList的详细教程

    泛型可以在类或方法中预支地使用未知的类型。这篇文章主要介绍了Java中关于泛型、包装类及ArrayList的详细教程,需要的朋友可以参考下
    2021-12-12
  • SpringBoot与Postman实现REST模拟请求的操作

    SpringBoot与Postman实现REST模拟请求的操作

    这篇文章主要介绍了SpringBoot与Postman实现REST模拟请求的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • 新手必备的IDEA常用设置总结

    新手必备的IDEA常用设置总结

    今天给大家总结了一些IDEA的常用设置,文中有非常详细的图文介绍,对正在学习使用IDEA的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05
  • Java详解线上内存暴涨问题定位和解决方案

    Java详解线上内存暴涨问题定位和解决方案

    本篇文章介绍了我在开发过程中遇到的线上内存暴涨的问题,以及定位问题原因和解决该问题的过程及思路,通读本篇对大家的学习或工作具有一定的价值,需要的朋友可以参考下
    2021-10-10
  • SpringBoot缓存Ehcache的使用详解

    SpringBoot缓存Ehcache的使用详解

    EhCache、Redis比较常用,使用Redis的时候需要先安装Redis服务器,本文给大家介绍SpringBoot缓存Ehcache的使用详解,感兴趣的朋友跟随小编一起看看吧
    2022-03-03
  • 完美解决idea moudle没有蓝色的小方块的问题

    完美解决idea moudle没有蓝色的小方块的问题

    这篇文章主要介绍了完美解决idea moudle没有蓝色的小方块的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Java的特点和优点(动力节点整理)

    Java的特点和优点(动力节点整理)

    由于Java语言的设计者们十分熟悉C++语言,所以在设计时很好地借鉴了C++语言。可以说,Java语言是一种比C++语言“还面向对象”的一种编程语言,下面通过本文说下java的特点和优点
    2017-03-03

最新评论