Java SPI机制总结系列之开发入门实例

 

原创/朱季谦

在该文章正式开始前,先对 Java SPI是什么做一个简单的介绍。

SPI,是Service Provider Interface的缩写,即服务提供者接口,单从字面上看比较抽象,你可以理解成,该机制就像Spring容器一样,通过IOC将对象的创建交给了Spring容器处理,若需要获取某个类的对象,就从Spring容器里取出使用即可。同理,在SPI机制当中,提供了一个类似Spring容器的角色,叫【服务提供者】,在代码运行过程中,若要使用到实现了某个接口的服务实现类对象,只需要将对应的接口类型交给服务提供者。服务提供者将会动态加载实现了该接口的所有服务实现类对象。
服务提供者的角色用下图来表示。

image

举一个例子来说明。

假如,假如Maven项目里有这样一个interface接口,接口全名“com.zhu.service.UserService”——

package com.zhu.service;public interface UserService {void getName();
}

创建一个“com.zhu.service.impl.AUserServiceImpl”实现类——

public class AUserServiceImpl implements UserService {@Overridepublic void getName() {System.out.println("这是A用户姓名");}
}

接着在resource资源里,创建一个META-INF.services目录,在该目录里,创建一个文件名与接口com.zhu.service.UserService一致的文件——

image

该com.zhu.service.UserService文件里写下com.zhu.service.impl.UserServiceImpl类名字——

image

这时候,就可以基于Java SPI动态加载到接口的实现类并执行了,我们写一个简单的测试类做验证——

public class Test {public static void main(String[] args) {ServiceLoader<UserService> serviceLoader = ServiceLoader.load(UserService.class);Iterator<UserService> serviceIterator = serviceLoader.iterator();while (serviceIterator.hasNext()) {UserService service = serviceIterator.next();service.getName();}
}}
}

执行该代码,ServiceLoader会加载到META-INF.services目录下的配置文件,找到对应接口全名文件,读取文件里的类名,再通过反射就可以进行实现类的实例化。既然能找到实现类的对象,那么不就可以基于父类引用指向子类对象,进而调用到实现类的getName()方法。该方法里执行打印语句 System.out.println("打印用户姓名"),打印结果如下,说明基于接口UserService,在程序动态加载并执行UserService接口实现。

image

Java SPI的机制玩法,就如上文这一整个过程的实现。

该机制存在一个缺陷,假如该接口对应的文件存在多份实现类,那么,它都会一起执行了。

我们增加多一个实现类BUserServiceImpl——

public class BUserServiceImpl implements UserService {@Overridepublic void getName() {System.out.println("这是B用户姓名");}
}

然后,在resource资源里的META-INF.services目录接口对应com.zhu.service.UserService文件里,将BUserServiceImpl实现类的全名增加到文件里——

image

其他原有的代码无需改动,直接执行Test的main方法,打印结果如下,可以看到,新增的BUserServiceImpl实现类的getName()也被运行了。

image

这就说明,Java SPI机制会将文件里配置的所有实现类都动态加载运行,稍微思考了一下,不难发现,若当中某个实现类的getName()出现异常,那么后面还没有执行到的其他实现类就会终止了。

因此,Dubbo框架在设计SPI机制时,只是参考了Java SPI的实现,但没有照搬,相比Java,Dubbo增强了SPI机制,可以针对请求动态得选择需要的接口实现类来运行,更加灵活方便。我在自己的另一边原创博文中,详细介绍过Dubbo SPI的原理,感兴趣的小伙伴可以阅读——《Dubbo2.7的Dubbo SPI实现原理细节》

SPI机制的优点很明显,当我们需要基于已有接口新增一个实现类功能时,只需要新增一个实现类代码,无需在原有代码逻辑上做改动,就可以实现新增类的功能逻辑了。

这种场景比较适合在报表或者处理Excel文档情况下,需针对一个新报表或者Excel做相应定制化处理,只需要基于SPI已有接口新增一个实现类即可。我会在后续文章中,将过去应用到SPI的实践经验做一下总结。

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

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

相关文章

Python之Matplotlib绘图调节清晰度

Python之Matplotlib绘图调节清晰度 文章目录 Python之Matplotlib绘图调节清晰度引言解决方案dpi是什么&#xff1f;效果展示总结 引言 使用python中的matplotlib.pyplot绘图的时候&#xff0c;如果将图片显示出来&#xff0c;或者另存为图片&#xff0c;常常会出现清晰度不够的…

【JAVA】在 Queue 中 poll()和 remove()有什么区别

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 poll() 方法&#xff1a; remove() 方法&#xff1a; 区别总结&#xff1a; 结语 我的其他博客 前言 在Java的Queue接口中&…

强化学习应用(六):基于Q-learning的物流配送路径规划研究(提供Python代码)

一、Q-learning算法简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于马尔可夫决策过程&#xff08;MDP&#xff09;的问题。它通过学习一个值函数来指导智能体在环境中做出决策&#xff0c;以最大化累积奖励。 Q-learning算法的核心思想是使用一个Q值函数来估计每…

day-09 删除排序链表中的重复元素

思路 从前往后遍历链表&#xff0c;当当前节点的值与下一个节点值相等时&#xff0c;删除下一节点&#xff1b;否则向后移动一个节点&#xff0c;继续遍历 解题方法 while(p!null&&p.next!null){ if(p.next.valp.val)p.nextp.next.next;//当前节点的值与下一个节点值相…

鸿蒙Harmony-层叠布局(Stack)详解

我们总是为了太多遥不可及的东西去拼命&#xff0c;却忘了人生真正的幸福不过是灯火阑珊处的温暖&#xff0c;柴米油盐的充实&#xff0c;人生无论你赚的钱&#xff0c;是多还是少&#xff0c;经历的事情是好还是坏&#xff0c;都不如过好当下的每一天&#xff01; 目录 一&am…

初始化数组

一、静态初始化格式&#xff1a; 数据类型[ ] 数组名 new 数据类型[ ]{元素1&#xff0c;元素2&#xff0c;元素3......} 等号后面的new 数据类型可以省略 注意&#xff1a;什么类型的数组只能存放什么类型的数据 直接打印a或b会显示其地址 数组的元素个数&#xff1a;arr…

C# 基础入门

第二章 C# 语法基础 2-1 C# 中的关键字 关键字&#xff0c;是一些被C#规定了用途的重要单词。 在Visual Studio的开发环境中&#xff0c;关键字被标识为蓝色&#xff0c;下图代码中&#xff0c;用红方框圈出的单词就是关键字。 关键字 class &#xff0c;这个关键字的用途是…

Linux下编写zlg7290驱动(1)

大家好&#xff0c;今天给大家介绍Linux下编写zlg7290驱动(1)&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 在智能仪表中&#xff0c;经常会用到键盘、数码管等外设。因此&…

【Java语言基础②】Java基本语法——Java程序基本格式,注释,标识符,常量

通过前面的学习&#xff0c;大家对Java语言有了一个基础认识&#xff0c;但现在还无法使用Java语言编写程序&#xff0c;要熟练使用Java语言编写程序&#xff0c;必须充分掌握Java语言的基础知识。今天咱们就来聊一聊Java的基本语法。 1.java程序的基本格式 Java程序代码必须…

Spring Boot 3 + Vue 3实战:引入数据库实现用户登录功能

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;创建数据库&#xff08;二&#xff09;创建用户表&#xff08;三&#xff09;后端项目引入数据库1、添加相关依赖2、用户实体类保持不变3、编写应用配置文件4、创建用户映射器接口5、创建用户服务类6、修改登录控制…

NLP论文阅读记录 - 2021 | WOS 使用深度强化学习及其他技术进行自动文本摘要

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作2.1. Seq2seq 模型2.2.强化学习和序列生成2.3.自动文本摘要 三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 Auto…

Java:常见算法

认识算法 什么是算法&#xff1f; 解决某个实际问题的过程和方法 学习算法的技巧 先搞清楚算法的流程直接去推敲如何写代码 排序算法 冒泡排序 每次从数组中找出最大值放在数组的后面去。 实现冒泡排序的关键步骤分析 确认总共需要做几轮&#xff1a;数组的长度-1每轮比较…

【java】创建打印数组的方法并调用

java的数组和Python不一样&#xff0c;不能直接用print打印&#xff0c;而如果每次都用循环的方法&#xff0c;比较麻烦&#xff0c;就直接创建一个类&方法&#xff0c;每次用的时候直接调用。 public class list_deal {public static void printArray(int[] arr){for (in…

Python实现对角但非同一性协方差结构回归模型(WLS算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 WLS回归分析是一种常用的回归分析方法&#xff0c;通过对数据进行加权处理&#xff0c;可以更准确地评…

VSCode编写 C/C++ 程序

VSCode 全称 Visual Studio Code&#xff0c;是微软出的一款轻量级代码编辑器&#xff0c;免费、开源而且功能强大。它支持几乎所有主流的程序语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性&#xff0c;支持插件扩展&#xff0c;并…

Day02

今日任务&#xff1a; 977 有序数组的平方209 长度最小的子数组59 螺旋矩阵Ⅱ 977 有序数组的平方 题目链接&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/ 双指针问题&#xff0c;以及数组本身时有序的&#xff1b; 思路&#xff1a; 左、右两个…

SG-8101CGA 系列 (晶体振荡器 可编程 可用 +125°C )

SG-8101CGA是可编程晶体振荡器&#xff0c;具有CMOS输出&#xff0c;适用于汽车&#xff0c;同时&#xff0c;该系列还提供相同的频率和其他参数的轻松编程能力&#xff0c;符合AEC-Q100标准&#xff0c;具有出色的电磁兼容性和稳定性&#xff0c;可以在各种环境下使用。外部尺…

Linux的DHCP工作原理和dns服务器

目录 一、DHCP原理 1.DHCP的好处 2.DHCP的分配方式 3.实验 二、dns服务器 1.什么是dns 2.dns域名解析 3、在内网搭建dns 一、DHCP原理 DCHP工作原理使用C/S架构 &#xff08;1&#xff09;第一步&#xff0c;客户端广播发送一个discover报文寻找DHCP服务器。 &#…

牛客周赛 Round 28 解题报告 | 珂学家 | 组合数学 + 离散化树状数组

前言 整体评价 还是E稍微有点意思&#xff0c;新周赛好像比预期要简单一些, _. 欢迎关注 珂朵莉 牛客周赛专栏 珂朵莉 牛客小白月赛专栏 A. 小红的新周赛 思路: 模拟 #include <bits/stdc.h>using namespace std;int main() {int res 0;for (int i 0; i < 6; i…