如何实现功能插件化

news2024/11/18 18:29:41

本文将介绍两种方式来实现功能插件化:

  1. Java SPI
  2. Spring factories

在整个插件化的方案中,会涉及到如下 3 个组成部分:

  1. 插件定义(即将插件定义为一个接口) 在这里插入图片描述

  2. 插件实现(即对插件接口的实现)
    在这里插入图片描述
    这里对同一个插件定义,有两个不同的实现,即 2 个插件:cab5-charging-policy-generalcab5-charging-policy-vip,实现了不同的扣款策略。

  3. 支持插件插拔的平台(因为不知道叫啥,姑且先叫「主项目」吧)

1、Java SPI

SPI 全称 Service Provider Interface,中文译为「服务提供者接口」,JDK 提供的一种服务发现机制,即为某个接口寻找具体的实现。

让我们结合开篇提到的插件化方案所涉及 3 个组成部分,来说明下如何用 SPI 来实现插件化。

  1. 我们要将插件化的功能用接口来进行定义,并接口打成一个 jar 包。

  2. 实现【步骤1】中定义的接口,并将该实现打成一个 jar 包。此时插件就已包装完成,下一步就是「主项目」引入该 jar 包(即插件)。

    这里有一个问题:

    随便一个 jar 包就能成为一个插件吗?

    答案当然是否定的。那问题又来了:

    是通过什么来标识 jar 包是一个插件的呢?

    我们需要在该 jar 包中 META-INF 目录下创建 services 子目录,同时,在该子目录下创建一个以接口(插件定义中的接口)名为文件名的文件,且文件中的内容为接口实现类的全限定名,如下:
    在这里插入图片描述

  3. 主项目引入插件并使用插件

    首先我们在「主项目」中需要引入「插件定义」以及相关的「插件实现(即插件)」,如下:在这里插入图片描述
    最后我们再来说下,如何在「主项目」中使用插件,如下图:
    在这里插入图片描述
    从图中我们可以看到,Java SPI 通过 java.util.ServiceLoader 将插件接口(即 cab5-charging-policy jar 中的 CharginigPolicyPluging)的实现类全部(即 cab5-charging-policy-general jar 中的 ChargingPolicyGeneral 和 cab5-charging-policy-vip jar 中的 ChargingPolicyVip)加载,并通过该类的 iterator 方法将实现插件接口(即 cab5-charging-policy jar 中的 CharginigPolicyPluging)的插件进行遍历(也就是分别调用了 cab5-charging-policy-general jar 中的 ChargingPolicyGeneral 和 cab5-charging-policy-vip jar 中的 ChargingPolicyVip 的 charging 方法)。
    在这里插入图片描述
    这里又有一个问题:

    ServiceLoader 是如何找到「插件接口」的实现类的呢?

    ServiceLoader 通过扫描「插件实现」的 jar 包中 META-INF/services 目录下的文件,从而得知接口与实现的对应关系,进而找到了接口的所有实现类。

2、Spring factories

Spring factories 是 Spring Boot 一种解耦的扩展机制,它仿照了 Java 的 SPI。采用 Spring factories 来实现功能插件化的过程与 Java SPI 非常类似。主要有以下 2 点不同:

  1. 将 jar 包标识为插件的方式不同

    Spring factories 需要我们在该 jar 包中的 META-INF 目录下创建 spring.factories 文件,文件内容为:接口=实现类的全限定名,如下: 在这里插入图片描述

  2. 「主项目」加载使用插件的方式不同

    我们需要使用 spring-core 包里的 org.springframework.core.io.support.SpringFactoriesLoader 来加载插件,如下图:
    在这里插入图片描述
    与 SPI 一样,这里也进一步说明下 SpringFactoriesLoader 是如何找到「插件接口」的实现类的:factories 是通过扫描「插件实现」的 jar 包中 META-INF/spring.factories 文件,从而得知接口与实现的对应关系,进而找到了接口的所有实现类。

3、示例代码

本文的上方有提供对应的示例代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/699935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【需求实现】输入多少就输出多少的拟合任务如何实现(二):进度条简化

文章目录 导读普通的输出方式上下求索TensorBoard是个不错的切入点与Callback参数对应的Callback方法官方的内置Callback官方进度条简单的猜测与简单的验证拼图凑齐了! 导读 在训练模型的过程中往往会有日志一堆一堆的困扰。我并不想知道,因为最后我会在…

今天给大家分享几款好用的卸载神器

在日常使用电脑的过程中,我们经常需要安装和卸载各种软件。然而,有时候使用操作系统自带的卸载程序可能无法完全清除程序及其相关文件和注册表项,导致系统出现垃圾文件和残留问题。为了解决这个困扰,今天我将向大家分享几款好用的…

【Spring】基于注解方式存取JavaBean:Spring有几种注入方式?有什么区别?

前言 Hello,我是小黄。众所周知,Spring是一个开源的Java应用程序框架,其中包括许多通过注解实现依赖注入的功能。Spring提供了多种注入方式,可以满足不同的需求和场景。常见的注入方式包括构造函数注入、Setter方法注入和属性注入…

【Redis】Redis的高可用与持久化

文章目录 一、Redis 高可用1. 概念2. 高可用技术以及作用2.1 持久化2.2 主从复制2.3 哨兵2.4 集群 二、Redis 持久化1. 持久化的功能2. Redis 持久化方式 三、RDB 持久化1. 概述2. 触发条件2.1 手动触发2.2 自动触发2.3 其他自动发机制 3. 执行流程4. 启动时加载 四、AOF 持久化…

Modin 入门学习

Modin 是一个 Python 第三方库,用于加速 Pandas 的 API 执行速度。原始的 Pandas 是单线程执行的,而 Modin 则重新打包了 Pandas 里面的 API,使其同时在多个内核中运行,提高硬件性能的利用率。 使用方法很简单,安装 M…

2.9C++多态

C 继承扩展 C继承在实际开发中它可以帮助我们实现代码重用,减少代码冗余,提高代码的可维护性和可扩展性。 通过继承,我们可以从已有的类中派生出新的类,新的类可以继承父类的属性和方法,并且可以添加自己的属性和方法…

selenium元素定位---ElementClickInterceptedException(元素点击交互异常)解决方法

目录 前言: 1、异常原因 2、解决方法: 前言: 当使用Selenium进行元素定位和交互时,可能会遇到ElementClickInterceptedException(元素点击交互异常)的异常。这通常是由于页面上存在其他元素或弹出窗口遮…

ROS学习之基础包创建的详细流程:包括rosnode, rostopic, rosrun,roslaunch等使用

0 引言 本文旨在学习ROS基础包的从零开始创建,包括如何创建一个发布消息节点,一个接收消息节点,还有如何使用roslaunch同时启动多个节点,如何编译ROS工程包等操作。 默认已在Ubuntu系统中安装ROS机器人系统,比如Ubun…

AOP--拦截器

AOP应用--拦截器Spring拦截器拦截器执行流程前缀的添加统一异常处理统一数据返回格式返回String类型 AOP应用–拦截器 AOP的作用:统一功能处理;我们将以三个内容作为学习的掌握点;而这三点也是我们非常迫切需要的 1:用户登录权限…

Windows系统分区大小

Microsoft Reserved(MSR)——保留分区——16MB左右 EFI System Partition(ESP)——系统分区——100MB左右 Recovery Partition(自起名字REP)——恢复分区——450MB左右 其他分区——剩余

对rabbitmq进行压测

添加rabbitmq依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactI…

C# PaddleOCR标注工具

基于以下开源项目改造的 https://gitee.com/BaoJianQiang/FastOCRLabel 效果 Demo下载

CMake使用gRPC(Protobuf) 的c++ demo

gRPC的命令参数里&#xff0c; 1. 如果要用pacakge&#xff0c;需要--proto_path的参数&#xff0c; 例如helloworld.proto的绝对路径是 /home/user/grpc_demo_ws/grpc_demo/hello_world/proto/helloworld.proto 在helloworld.proto里面的pacakge是 package grpc_demo.hello_w…

同步(通信原理)

同步原理&#xff1a; 在通信系统中&#xff0c;同步是指发送端和接收端在时间上保持一致&#xff0c;使得接收端能够正确地解析和还原发送端发送的信号。同步的原理可以根据具体的通信系统和协议来区分&#xff0c;下面是几种常见的同步原理&#xff1a; 1. 时钟同步&#x…

uniapp 配置chooseLocation微信小程序腾讯地图选点

uniapp 配置chooseLocation微信小程序腾讯地图选点 场景 在uniapp中使用地图选点 搜索功能&#xff0c;回显功能&#xff0c;移动选点功能 使用到的API是uni.chooseLocation 详细看一下都有哪些属性 latitude &#xff1a;目标地纬度 Number longitude &#xff1a;目标地经度…

论文阅读: (CVPR2023 SDT )基于书写者风格和字符风格解耦的手写文字生成及源码对应

目录 引言SDT整体结构介绍代码与论文对应搭建模型部分数据集部分 总结 引言 许久不认真看论文了&#xff0c;这不赶紧捡起来。这也是自己看的第一篇用到Transformer结构的CV论文。之所以选择这篇文章来看&#xff0c;是考虑到之前做过手写字体生成的项目。这个工作可以用来合成…

浅析基于物联网技术的校园能耗智慧监控平台的设计及应用

摘 要&#xff1a;为打造低碳绿色校园&#xff0c;营造良好的学习环境&#xff0c;针对目前校园建筑能耗大&#xff0c;特别是空调节能困难等问题&#xff0c;特采用物联网技术构建校园建筑能耗智慧监控平台。通过设计空调监控子系统&#xff0c;搭建空调监控模型实现了空调等智…

在 Jetpack Compose 中使用 Snackbar

Jetpack Compose 是 Android 的现代 UI 工具库&#xff0c;提供了丰富的组件和功能来构建漂亮、交互丰富的用户界面。在本文中&#xff0c;我们将学习如何在 Jetpack Compose 中使用 Snackbar 组件来显示临时消息或操作反馈。 什么是 Snackbar&#xff1f; Snackbar 是一种用于…

基于Layui实现管理页面

基于Layui实现的后台管理页面&#xff08;仅前端&#xff09; 注&#xff1a;这是博主在帮朋友实现的一个简单的系统前端框架&#xff08;无后端&#xff09;&#xff0c;跟大家分享出来&#xff0c;可以直接将对应菜单跟html文件链接起来&#xff0c;页面使用标签页方式存在&…

面试了一个前阿里P7,Java八股文与架构核心知识简直背得炉火纯青

前几天&#xff0c;跟个老朋友吃饭&#xff0c;他最近想跳槽去大厂&#xff0c;觉得压力很大&#xff0c;问我能不能分享些所谓的经验套路。 每次有这类请求&#xff0c;都觉得有些有趣&#xff0c;不知道你发现没有大家身边真的有很多人不知道怎么面试&#xff0c;也不知道怎…