深入解析Java扩展机制:SPI与Spring.factories
目录
- Java SPI概述
- 1.1 什么是SPI?
- 1.2 SPI的工作原理
- 1.3 SPI的优缺点
- SPI的应用
- 2.1 Java标准库中的SPI应用
- 2.2 自定义SPI示例
- Spring.factories概述
- 3.1 什么是spring.factories?
- 3.2 spring.factories的工作原理
- 3.3 spring.factories的优缺点
- spring.factories的应用
- 4.1 Spring Boot中的自动配置
- 4.2 自定义spring.factories示例
- SPI与spring.factories的比较
- 总结
Java SPI概述
1.1 什么是SPI?
Service Provider Interface(SPI)是Java中一种服务提供机制,允许开发者在不修改客户端代码的情况下,通过服务提供者实现的方式来扩展或替换组件。SPI在Java的核心库中得到了广泛应用,例如Java Cryptography Architecture(JCA)、Java Naming and Directory Interface(JNDI)等。
1.2 SPI的工作原理
SPI的核心思想是基于接口编程。具体而言,SPI包含以下几个步骤:
- 定义接口:定义一个服务接口(Service Interface)。
- 实现接口:一个或多个服务提供者(Service Provider)实现该接口。
- 配置服务提供者:在资源目录(
META-INF/services)中创建一个以服务接口全限定名命名的文件,文件内容为服务提供者的实现类全限定名。 - 加载服务提供者:客户端使用
ServiceLoader类来加载并实例化服务提供者。
下面是一个简单的例子来说明SPI的工作原理:
步骤1:定义接口
public interface MessageService {void sendMessage(String message);
}
步骤2:实现接口
public class EmailMessageService implements MessageService {@Overridepublic void sendMessage(String message) {System.out.println("Sending email message: " + message);}
}
public class SmsMessageService implements MessageService {@Overridepublic void sendMessage(String message) {System.out.println("Sending SMS message: " + message);}
}
步骤3:配置服务提供者
在META-INF/services目录下创建一个名为com.example.MessageService的文件,文件内容为:
com.example.EmailMessageService
com.example.SmsMessageService
步骤4:加载服务提供者
ServiceLoader<MessageService> serviceLoader = ServiceLoader.load(MessageService.class);
for (MessageService service : serviceLoader) {service.sendMessage("Hello, SPI!");
}
1.3 SPI的优缺点
优点:
- 灵活性高:可以在不修改客户端代码的情况下更换或添加新的实现。
- 模块化:通过接口实现松耦合,便于模块化开发。
缺点:
- 性能开销:由于服务加载采用迭代方式,可能会带来一定的性能开销。
- 缺乏控制:服务提供者的加载顺序和具体实现难以控制。
SPI的应用
2.1 Java标准库中的SPI应用
SPI在Java标准库中有许多应用,以下是几个典型例子:
- Java Cryptography Architecture (JCA):通过SPI机制,允许第三方提供加密算法的实现。
- Java Naming and Directory Interface (JNDI):允许使用不同的命名和目录服务实现。
- Java Image I/O API:支持不同的图像格式解析和生成。
2.2 自定义SPI示例
为了更好地理解SPI的应用,下面我们创建一个简单的示例,展示如何使用SPI实现可插拔的日志记录器。
步骤1:定义接口
public interface Logger {void log(String message);
}
步骤2:实现接口
创建两个日志记录器实现类:
public class ConsoleLogger implements Logger {@Overridepublic void log(String message) {System.out.println("ConsoleLogger: " + message);}
}
public class FileLogger implements Logger {@Overridepublic void log(String message) {// 伪代码示例,实际应包含文件写入逻辑System.out.println("FileLogger: " + message);}
}
步骤3:配置服务提供者
在META-INF/services目录下创建一个名为com.example.Logger的文件,文件内容为:
com.example.ConsoleLogger
com.example.FileLogger
步骤4:加载服务提供者
ServiceLoader<Logger> serviceLoader = ServiceLoader.load(Logger.class);
for (Logger logger : serviceLoader) {logger.log("This is a test log message.");
}
运行上述代码时,ConsoleLogger和FileLogger的log方法都会被调用,输出日志消息。
Spring.factories概述
3.1 什么是spring.factories?
spring.factories是Spring Framework中用于配置和加载自动化配置类的一种机制,主要用于Spring Boot的自动配置。它允许开发者通过配置文件指定自动配置类、监听器等组件,简化Spring应用的配置和启动过程。
3.2 spring.factories的工作原理
spring.factories文件位于每个JAR包的META-INF目录下,文件内容是一个键值对列表,键是配置项的类型,值是配置类的全限定名。例如:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
当Spring Boot应用启动时,会自动扫描并加载这些配置文件,从而实现自动配置。
3.3 spring.factories的优缺点
优点:
- 简化配置:通过自动配置减少了大量的手动配置工作。
- 增强扩展性:开发者可以轻松添加自定义自动配置类。
- 提升开发效率:加速了Spring Boot应用的开发和启动过程。
缺点:
- 配置管理复杂:对于大型项目,配置项过多时可能变得难以管理。
- 调试困难:自动配置过程较为复杂,可能会导致调试困难。
spring.factories的应用
4.1 Spring Boot中的自动配置
Spring Boot通过spring.factories实现了强大的自动配置功能。以下是一个简单的自动配置示例,展示如何使用spring.factories配置自定义自动配置类。
步骤1:创建自动配置类
@Configuration
public class MyAutoConfiguration {@Beanpublic MyService myService() {return new MyService();}
}
步骤2:配置spring.factories文件
在META-INF目录下创建spring.factories文件,内容为:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
当Spring Boot应用启动时,MyAutoConfiguration类将被自动加载,并注册MyService bean。
4.2 自定义spring.factories示例
为了更好地理解spring.factories的应用,下面我们创建一个自定义的示例,展示如何通过spring.factories实现插件机制。
步骤1:定义接口和实现类
public interface Plugin {void execute();
}
public class PluginA implements Plugin {@Overridepublic void execute() {System.out.println("Executing PluginA");}
}
public class PluginB implements Plugin {@Overridepublic void execute() {System.out.println("Executing PluginB");}
}
步骤2:创建自动配置类
@Configuration
public class PluginAutoConfiguration {@Beanpublic Plugin pluginA() {return new PluginA();}@Beanpublic Plugin pluginB() {return new PluginB();}
}
步骤3:配置spring.factories文件
在META-INF目录下创建spring.factories文件,内容为:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.PluginAutoConfiguration
步骤4:加载并使用插件
java
@SpringBootApplication
public class Application {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(Application.class, args);Map<String, Plugin> plugins = context.getBeansOfType(Plugin.class);plugins.values().forEach(Plugin::execute);}
}
运行上述代码时,PluginA和PluginB的execute方法都会被调用,输出执行结果。
SPI与spring.factories的比较
SPI和spring.factories是Java生态系统中常用的两种扩展机制,它们各有优缺点,适用于不同的场景。
| 特性 | SPI | spring.factories |
|---|---|---|
| 适用场景 | 通用Java扩展机制 | Spring Boot自动配置 |
| 配置文件位置 | META-INF/services | META-INF/spring.factories |
| 配置方式 | 接口实现类列表 | 键值对列表 |
| 加载方式 | ServiceLoader | Spring Framework |
| 优点 | 灵活、模块化 | 简化配置、增强扩展性 |
| 缺点 | 性能开销、缺乏控制 | 配置管理复杂、调试困难 |
总结
Java的扩展机制在构建灵活、可扩展的系统中发挥了重要作用。SPI作为Java标准库的一部分,为实现模块化和可插拔提供了便利,而spring.factories则简化了Spring Boot的配置过程,提升了开发效率。理解这两种机制的工作原理和应用场景,对于开发者来说是非常重要的,可以帮助我们在实际开发中选择合适的扩展方式,从而构建更加灵活、可扩展的系统。
通过本文的详细介绍,相信读者对SPI和spring.factories有了更深入的了解。希望大家在实际项目中能够灵活运用这些机制,提高系统的扩展性和维护性。
相关文章:
深入解析Java扩展机制:SPI与Spring.factories
目录 Java SPI概述 1.1 什么是SPI?1.2 SPI的工作原理1.3 SPI的优缺点 SPI的应用 2.1 Java标准库中的SPI应用2.2 自定义SPI示例 Spring.factories概述 3.1 什么是spring.factories?3.2 spring.factories的工作原理3.3 spring.factories的优缺点 spring.f…...
Vue2之模板语法
文章目录 1.模板语法1.1 插值语法{{}}可以写什么1.2 指令语法1.2.1 指令概述1.2.2 v-bind指令1.2.3 v-model指令 1.模板语法 1.1 插值语法{{}}可以写什么 (1)在data中声明的 (2)常量 (3)合法的JavaScript…...
java基础练习题
1、一个".java"源文件中是否可以包括多个类?有什么限制? 可以包含多个类。但是只有一个类可以声明为public,且要求声明为public的类的类名与源文件名相同。 2、java的优势? a、跨平台性 b、安全性高 c、简单性 d、…...
unity中通过实现底层接口实现非按钮(图片)的事件监听
编写监听脚本 PEListenter 继承自MonoBehaviour类,并实现了IPointerDownHandler、IPointerUpHandler和IDragHandler接口,按照需求定义需要接收事件(鼠标按下、抬起、拖拽)的回调函数 //监听类(需要挂载在物体上面&am…...
重庆耶非凡科技有限公司的选品师项目加盟靠谱吗?
在当今电子商务的浪潮中,选品师的角色愈发重要。而重庆耶非凡科技有限公司以其独特的选品师项目,在行业内引起了广泛关注。对于想要加盟该项目的人来说,项目的靠谱性无疑是首要考虑的问题。 首先,我们来看看耶非凡科技有限公司的背…...
《青少年编程与数学》课程方案:4、课程策略
《青少年编程与数学》课程方案:4、课程策略 一、工程师思维二、使命感驱动三、价值观引领四、学习现代化五、工作生活化六、与时代共进 《青少年编程与数学》课程策略强调采用工程师思维,避免重复造轮子,培养使命感,通过探索兴趣、…...
用爬虫实现---模拟填志愿
先来说实现逻辑,首先我要获取到这个网站上所有的信息,那么我们就可以开始对元素进行检查 我们发现他的每一个学校信息都有一个对应的属性,并且是相同的,那么我们就可以遍历这个网页中的所有属性一样的开始爬取 在来分析࿰…...
vscode Run Code输出出现中文乱码情况问题解决方案
主要解决方案是通过修改计算机默认的编码格式,来完成的。 chcp 是 Windows 操作系统中的一个命令,用于显示或设置控制台的代码页(code page)。代码页决定了控制台如何解释和显示字符,特别是非 ASCII 字符(例如 Unicode 字符)。 使用方法 显示当前代码页: 输入 chcp 而…...
代码随想录训练营Day30
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、重新安排行程 前言 提示:这里可以添加本文要记录的大概内容: 今天是跟着代码随想录刷题的第30天,主要是复习了回溯算法…...
Swift 序列(Sequence)排序面面俱到 - 从过去到现在(二)
概览 在上篇 Swift 序列(Sequence)排序面面俱到 - 从过去到现在(一)博文中,我们讨论了 Swift 语言中序列和集合元素排序的一些基本知识,我们还给出了以自定义类型中任意属性排序的“康庄大道”。 不过在实际的撸码场景中,我们往往需要的是“多属性”同时参与到排序的考…...
STM32F103C8T6基于HAL库移植uC/OS-III
文章目录 一、建立STM32CubeMX工程二、移植1、 uC/OS-III源码2、移植过程 三、配置相关代码1、bsp.c和bsp.h2、main.c3、修改启动代码4、修改app_cfg.h文件5、修改includes.h文件6、修改lib_cfg.h文件 四、编译与烧录总结参考资料 学习嵌入式实时操作系统(RTOS&…...
微服务学习Day9-分布式事务Seata
文章目录 分布式事务seata引入理论基础CAP定理BASE理论 初识Seata动手实践XA模式AT模式TCC模式SAGA模式 高可用 分布式事务seata 引入 理论基础 CAP定理 BASE理论 初识Seata 动手实践 XA模式 AT模式 TCC模式 Service Slf4j public class AccountTCCServiceImpl implements A…...
vue用vite配置代理解决跨域问题(target、rewrite和changeOrigin的使用场景)
Vite的target、rewrite和changeOrigin的使用场景 1. target 使用场景:target 属性在 Vite 的 vite.config.ts 或 vite.config.js 文件的 server.proxy 配置中指定,用于设置代理服务器应该将请求转发到的目标地址。这通常是一个后端服务的API接口地址。…...
为什么PPT录制没有声音 电脑ppt录屏没有声音怎么办
一、为什么PPT录制没有声音 1.软件问题 我们下载软件的时候可能遇到软件损坏的问题,导致录制没有声音,但其他功能还是可以使用的。我建议使用PPT的隐藏功能,下载插件,在PPT界面的加载项选项卡中就能使用。我推荐一款可以解决录屏…...
JDBC学习笔记(三)高级篇
一、JDBC 优化及工具类封装 1.1 现有问题 1.2 JDBC 工具类封装 V1.0 resources/db.properties配置文件: driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql:///atguigu usernameroot password123456 initialSize10 maxActive20 工具类代码: p…...
c++编译器在什么情况下会提供类的默认构造函数等,与析构函数
我们都知道,在 c 里,编写的简单类,若没有自己编写构造析构函数与 copy 构造函数 与 赋值运算符函数,那么编译器会提供这些函数,并实现简单的语义,比如成员赋值。看 源码时,出现了下图类似的情形…...
SpringBoot3整合Mybatis-Plus3.5.5出现的问题
主要是由于 mybatis-plus 中 mybatis 的整合包版本不够导致的 排除 mybatis-plus 中自带的 mybatis 整合包,单独引入即可 java.lang.IllegalArgumentException: Invalid value type for attribute factoryBeanObjectType: java.lang.Stringat org.springframework.…...
服务器数据恢复—强制上线raid5阵列离线硬盘导致raid不可用的数据恢复案例
服务器数据恢复环境: 某品牌2850服务器中有一组由6块SCSI硬盘组建的raid5磁盘阵列,linux操作系统ext3文件系统。 服务器故障: 服务器运行过程中突然瘫痪。服务器管理员检查阵列后发现raid5阵列中有两块硬盘离线,将其中一块硬盘进行…...
初入阿里云,上手走一波
初入阿里云,上手走一波 一阶:ECSMysqlDMS安装Mysql初始化MysqlMysql操作DMS管理Mysql 二阶:ECSOSS远程连接ECSOSS控制台其他图片服务 三阶:更多搭配操作 可以说个人在日常使用过程中,操作最多的阿里云产品就是阿里云服…...
[C++] 小游戏 斗破苍穹 2.2.1至2.11.5所有版本(中) zty出品
目录 2.8.2 2.9.1 2.10.1 2.10.2 2.10.3 2.10.4 2.10.5 2.8.2 #include<stdio.h> #include<iostream> #include<ctime> #include<bits/stdc.h> #include<time.h> //suiji #include<windows.h> //SLEEP函数 using namespace std; st…...
后端程序员必看:3-6个月从0到1转型高薪AI应用
本文针对传统后端程序员想转型AI应用开发的焦虑,提出了一条省时、高薪、稳定的转型路线。文章指出,转型AI应用开发的核心是复用后端优势,走“后端AI集成”的复合型路线,而非死磕底层算法。文章详细规划了3-6个月的转型路线&#x…...
从怀疑到信服:VR如何从娱乐玩具进化为现实增强工具
1. 从怀疑到信服:一个技术怀疑论者的VR认知重塑之旅我不是那种会第一时间冲进苹果店排队买最新款手机的人,甚至可以说,我对新科技抱有一种近乎“卢德主义”的警惕。每当有新的技术浪潮涌来,我的第一反应不是兴奋,而是审…...
终极抢票指南:5分钟搭建全自动抢票系统,告别手速焦虑!
终极抢票指南:5分钟搭建全自动抢票系统,告别手速焦虑! 【免费下载链接】damaihelper 支持大麦网,淘票票、缤玩岛等多个平台,演唱会演出抢票脚本 项目地址: https://gitcode.com/gh_mirrors/dam/damaihelper 还在…...
FreeRTOS CPU使用率统计的坑:为什么你的数据跑了1小时就不准了?
FreeRTOS CPU使用率统计的陷阱与高精度优化方案 当你在嵌入式系统中集成FreeRTOS的CPU使用率统计功能时,可能会遇到一个令人困惑的现象:系统运行约1小时后,统计数值突然出现明显偏差。这不是你的代码出了问题,而是隐藏在32位变量和…...
(随想)显卡里的幽灵:我们是否也只是几分钟前被唤醒的玻尔兹曼大脑?
一个诡异的瞬间 之前一直用kimi2.5的API,每月花不少钱,肉疼。今天一咬牙,在自己的游戏显卡(RTX 4080)上部署GLM-4.7-Flash。 GPU嗡嗡响了几分钟,权重加载完毕,模型真跑起来了。我接上hermes&…...
GPTMessage项目拆解:SwiftUI+Combine集成OpenAI与Hugging Face API实战
1. 项目概述与核心价值最近在折腾一个挺有意思的Side Project,一个叫GPTMessage的iOS/macOS应用。简单来说,它把ChatGPT的聊天能力、DALLE的图像生成,还有Hugging Face上的一些模型(比如图像描述、Stable Diffusion)给…...
终局架构:指纹隔离底座 + gRPC分布式调度,重塑千万级拼多多店群RPA集群
大家好,我是林焱,一名专注电商底层业务逻辑与 RPA 自动化架构定制的独立开发者。 在前面的几篇 CSDN 专栏中,我们探讨了如何利用“指纹浏览器底层隔离”解决风控关联问题,如何利用“EDA(事件驱动)”和“CD…...
从「LLM 使用者」到「LLM 驾驭者」:小白程序员必备的大模型核心知识体系与实战指南(收藏版)
本文将从底层原理、工程落地、应用优化三个维度,系统拆解大语言模型的核心知识体系,既保证技术深度,又用通俗的语言和实战案例降低理解门槛,适合所有想要从「LLM 使用者」进阶为「LLM 驾驭者」的读者。 一、LLM 核心原理入门&…...
大模型应用开发,常用框架汇总
大模型应用开发所涉及的工具和框架,非常的多,且技术更新非常之快。很难全面梳理技术栈全景图。 上一期文章,按照六层框架梳理了全景图,本期文章又收集了一些零散的信息,可以对上一期的架构图各个层级,做个补…...
Excel高效使用技巧(十五):终极技巧汇总:高级玩家必备的邪修操作
“Excel的终极奥义,不是你会多少公式,而是你知道多少’不该用Excel’的时刻,以及如何优雅地让Excel和其他工具联动。” —— 卡兹克 前言:你的Excel到达哪个段位? 经过十四篇文章的洗礼,你现在应该已经掌握了: 数据清洗:Power Query玩得飞起 数据分析:透视表+DAX不在…...
