ServiceLoader : JAVA SPI 机制

使用Java的java.util.ServiceLoader实现服务发现和加载 Java标准库中的java.util.ServiceLoader类提供了一种简单而强大的机制来实现服务发现和加载。通过定义服务接口和实现服务提供者,并在META-INF/services目录下声明服务提供者的类名,我们可以利用ServiceLoader动态地加载和使用外部提供的服务。在上面的示例中,我们通过调用ServiceLoader.load方法来加载MessageService接口的实现。然后,我们可以使用for-each循环遍历所有的服务提供者,并调用它们的sendMessage方法。 阅读详情

SPI的全名为Service Provider Interface.普通开发人员可能不熟悉,因为这个是针对厂商或者插件的。在java.util.ServiceLoader的文档里有比较详细的介绍。

简单来说就是通过配置文件指定接口的实现类。

当我们开发一套框架、一套机制、一个插件或一套API时候,如果需要第三方的服务支持,可以直接写死到代码里面,但这种方式耦合太强,不利于切换到其它服务,好的方法是写一个配置文件指定服务的实现方,幸运的是java的spi机制已经帮我们做好了,示例用法如下:

一个接口:

package testws;

public interface TestEJB {
    void test(String data) throws Exception;
    void test0(String data) throws Exception;
}
第一个实现类:

package testws;

public class MyTest implements TestEJB {
    public void test(String data) throws Exception {
        System.out.println("my test:" + data);
    }

    public void test0(String data) throws Exception {
        System.out.println("test0:" + data);
    }
}
第二个实现类:

package testws;

public class MyTest2 implements TestEJB {
    public void test(String data) throws Exception {
        System.out.println("my test2222:" + data);
    }

    public void test0(String data) throws Exception {
        System.out.println("test02222222:" + data);
    }
}

建立 META-INF 文件夹,在其里面建立 services 文件夹,在services文件夹下建立一个文件,名称为我们需要实现的服务的全类名,即:testws.TestEJB

文件testws.TestEJB的内容如下:(PS:如果我们只需要一个实现类,下面可以只写一个,每一个实现类占一行)

testws.MyTest
testws.MyTest2

最后一个步骤:将三个java类和META-INF 文件夹打包到一个jar中,就可以使用了,使用方式:

import java.util.ServiceLoader;

public class TestSPI {
    public static void main(String[] args) {
        ServiceLoader<TestEJB> loadedImpl = ServiceLoader.load(TestEJB.class);
        for (TestEJB testEJB : loadedImpl) {
            System.out.println(testEJB.getClass());
            try {
                testEJB.test("a");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

打印如下:

class testws.MyTest
my test:a
class testws.MyTest2
my test2222:a


【项目实战】Java SPI机制详解:ServiceLoader的动态扩展实现 Java SPI机制通过标准化服务发现与加载,实现程序动态扩展。核心组件包括服务接口、实现类和ServiceLoader,工作流程通过配置文件(META-INF/services/)绑定接口与实现。该机制解耦代码依赖,支持热替换,广泛应用于JDBC驱动、日志框架等场景。使用时需注意实现类需有无参构造、线程安全及延迟加载特性。SPI已成为Java生态标配,如Spring Boot 86%自动配置类采用该机制,显著提升框架灵活性。 阅读详情

相关推荐

MRI脑影像分析从哲学到技术:一文搞懂VBM预处理基本原理(全网最详细解析)

   分析大脑解剖学差异最常用方法之一是基于体素的形态学方法(voxel-based morphometry, VBM)。 VBM的基本思想是测量大脑组织,尤其是灰质的局部浓度的差异。在大脑的每个体素处进行操作,然后在两个或多个实验组之间进行统计比较,从而在受调查的组之间建立特定大脑区域中脑组织浓度的统计学显着差异。 VBM分析基于(高分辨率)MRI脑部扫描,涉及大量处理步骤,主要是空间归一化,分割,平滑和统计分析,最终结果是统计图,显示了各组之间组织类型明显不同的区域[^1]。 参考 [^1] ..

意疏的学习笔记 3万+

深入了解Java的ServiceLoader类

的主要用途是加载和实例化服务提供者,这里的“服务”通常指的是实现了某个接口的类。在这些场景中,核心代码定义了服务接口,而服务提供者(第三方或用户自定义)则实现了这些接口。SPI允许第三方为某个接口提供实现,并将这些实现类配置在特定的目录下。在Java的编程世界中,有时我们需要为某个接口提供多种实现,并且在运行时动态地加载这些实现。,核心代码可以在运行时动态地加载和使用这些服务提供者,而无需在编译时知道它们的存在。使用示例,演示了如何定义一个服务接口、实现该接口、配置服务提供者,以及使用。

qq_18596743的博客 3672

OLED的字模提取(保姆级)---基于PCtoLCD2013

做为一个刚刚开始接触编程不久的白菜,这个OLED想做一个信息显示,可是商家给我的例程里就是88,816两种字体的格式,我的屏幕是0.91寸的8*16的字体显示上感觉特别丢丢儿小,我就想整个大的,哎,只怪直接学习习惯不好,总是学一半,绕了好大一圈,才搞好,想写一篇博客,时刻提醒踏实学习,第一次写博客,小白一枚,勿喷。。 OLED屏幕驱动程序功能 我们对Markdown编辑器进行了一些功能拓展与语法支...

qq_44886611的博客 7781

java.util.ServiceLoader学习

    在java中根据一个子类获取其父类或接口信息非常方便,但是根据一个接口获取该接口的所有实现类却没那么容易。    有一种比较笨的办法就是扫描classpath所有的class与jar包中的class,然后用ClassLoader加载进来,然后再判断是否是给定接口的子类。但是很显然,不会使用这种方法,代价太大。    java本身也提供了一种方式来获取一个接口的子类,那就是使用java.ut...

星翔宇尘的博客 688

Windows 11 24H2 外接显卡坞兼容性实测:3步解决USB设备失效

本文详细解析了Windows 11 24H2系统下外接显卡坞导致USB设备失效的问题,并提供了三步终极解决方案:驱动预解压与手动更新、电源管理设置调整、优化的设备连接顺序。通过雷电3接口的兼容性优化,帮助用户解决键盘鼠标卡死等常见问题,提升外接显卡坞的稳定性与性能。

weixin_31714129的博客 590

手把手教你用单结晶体管搭建简易振荡电路(含电路图和波形分析)

本文详细介绍了如何使用单结晶体管(UJT)搭建简易振荡电路,包括电路设计、波形分析和实战技巧。通过具体的电路图和参数计算,帮助电子爱好者和工程师快速掌握UJT振荡器的设计与调试方法,适用于脉冲信号生成和时钟源制作等应用场景。

weixin_29207533的博客 516

java.util.ServiceLoader使用

今天在看hadoop源代的时候发现,在FileSystem中用到了java.util.ServiceLoader这个类来从配置文件中加载子类或者接口的实现类。以前从来没有使用过这个类,进去大概看了一下具体的实现。主要是从META-INF/services这个目录下的配置文件加载给定接口或者基类的实现,ServiceLoader会根据给定的类的full name来在META-INF/services

石头的专栏 1万+

FT2004(D2000)开发实战之AMD R5 230显卡驱动适配

AMD R5 230显卡驱动适配

嵌入式Linux 3199

Java-深入理解ServiceLoader类与SPI机制

Java-ServiceLoader类与SPI机制 引子 对于Java中的Service类和SPI机制的透彻理解,也算是对Java类加载模型的掌握的不错的一个反映。 了解一个不太熟悉的类,那么从使用案例出发,读懂源代码以及代码内部执行逻辑是一个不错的学习方式。 一、使用案例 通常情况下,使用ServiceLoader来实现SPI机制。 SPI 全称为 (Service Provider Inte...

li_xunhuan的博客 1158

S7-200 SMART PLC 子程序功能块(阀门控制)

由于S7-200 SMARTPLC的子程序种种功能、容量限制,有时想实现多次调用的子程序可能并不是太容易,这篇博客还是给出一些推荐写法,供大家参看。

RXXW_Dor的博客 8068

使用Qt和MX Component插件实现与菱PLC的通信

在本文中,我们介绍了如何使用Qt和MX Component插件实现与菱PLC的通信。我们首先安装和配置了MX Component插件,并在Qt项目中初始化和使用MX Component来连接、读取和写入PLC的数据。安装完成后,您需要在Qt项目中配置MX Component的路径,以便Qt可以找到所需的库文件。在本文中,我们将探讨如何使用Qt和MX Component插件来实现与菱PLC的通信。在主函数中,我们将初始化MX Component,并创建一个与PLC通信的示例。在上面的代码中,我们使用了。

TlScratch的博客 996

Java的SPI机制——动态加载ServiceLoader

核心代码仅依赖接口,不直接引用实现类,避免了 “硬编码 new 实现类” 的耦合问题,修改 / 替换实现无需改动核心代码。最核心的价值:第三方只需遵循 SPI 规范实现接口、配置文件,无需修改原有程序,即可无缝接入扩展。)由核心框架 / 模块定义,实现类(如 MySQL/Oracle 驱动)由第三方提供;符合规范的第三方 / 模块化服务实现,无需硬编码依赖,支持可插拔的扩展。,常见的数据库驱动厂商分别有不同的实现,如Mysql的驱动常用的有。配置文件内容:每行写一个实现类的全限定名(支持多个实现)。

SpringBoy的博客 862

非结构化数据在大数据湖中的应用实践

想象一下,你正在整理一个杂乱的书房。有些书整整齐齐地放在书架上,每本书都有明确的标题、作者和出版日期——这些就是结构化数据,它们像数据库中的表格,有固定的格式和字段。但书房里还有更多东西:散落的照片、手写的笔记、录音带、视频光盘、甚至还有画作。这些物品没有固定的格式,每件都独一无二——这就是非结构化数据。在技术术语中,非结构化数据是指没有预定义数据模型或组织形式的信息。文本文档(Word、PDF、TXT)电子邮件和社交媒体内容图像和照片(JPG、PNG)音频文件(MP3、WAV)

软件工程实践的博客 361

Java:深入理解ServiceLoader类与SPI机制

Java:深入理解ServiceLoader类与SPI机制一、SPI接口介绍1.1 SPI与API区别1.2 应用场景二、Demo展示三、源码分析四、总结 一、SPI接口介绍 SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制,可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用,比如java.sql.Driver接口,其他不同厂商可以针对同一接口做出不同的实现,MySQL和PostgreSQL都有不同的实现提供给用户,而Java的SPI机制可以为某

Jeffery的博客 1462

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

serviceloader java_Java SPI机制 - ServiceLoader

最近项目中使用了Java SPI机制,利用ServiceLoader来加载并实例化类。本文对Java SPI机制进行学习并对ServiceLoader进行源码分析。参见文章Java SPI机制和 ServiceLoader源码分析。SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。Java SPI...

weixin_39877050的博客 407

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java SPI机制介绍与ServiceLoader应用

1、SPI是什么 SPI全称Service Provider Interface(服务提供接口),是专门被第三方实现或者扩展的API,可以用来启用框架扩展和替换组件,提供了为某个接口寻找对应服务类的机制。 整体机制如下: (图片来源:https://www.jianshu.com/p/46b42f7f593c) Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机...

noaman_wgs的博客 1147

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

COLA扩展点SPI机制:基于Java ServiceLoader的实现原理

SPI(Service Provider Interface,服务提供者接口)是一种服务发现机制,允许第三方为接口提供实现并动态加载。在Java生态中,SPI通过`java.util.ServiceLoader`实现,广泛应用于插件化架构设计。COLA(Clean Object-oriented & Layered Architecture,整洁面向对象分层架构)框架的扩展点机制基于SPI思想,结...

gitblog_00978的博客 1075

Java SPI 机制与 ServiceLoader 源码解析:为什么 JDBC 能自动找到驱动

/ 接口// 实现// 使用方就三步——定义接口、写实现、一行文件注册。用文件代替硬编码。ServiceLoader 的源码实现属于"够用"级别——逻辑简单,60 行核心代码,没有魔法。你要是愿意,自己照着写一个更好的也不难。如果你在用 Spring Boot,优先用 Spring Factories。Java SPI 用在无 Spring 依赖的轻量扩展点上更合适。文中源码来自。

weixin_39042870的博客 223

java ServiceLoader和spi机制

spi spi(Service Provider Interface)是一种服务发现机制。可以实现这样一种机制。由框架定义好接口,其他拓展包或者程序实现这个了这个接口后,可以通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。 例子 新建一个模块,定义接口: HelloService public interface HelloService { String sayHello(); } 新建另外一个模块,实现接口: ChineseHell

rain_zhao_0102的博客 380

Java | SPI机制 | ServiceLoader源码分析

问题 最近学习dubbo源码的时候,接触了spi机制。如果不了解这的话,dubbo源码或许看起来你会迷惑。 那么什么是SPI机制呢?实际项目中又是怎么使用的呢? 背景 当我们开发项目中如果需要第三方的服务支持,可以直接写死到代码里面,指定具体实现。但这种方式耦合太强,不利于切换到其它服务,好的方法是写一个配置文件指定服务的实现方,这个时候java的spi机制就能发挥作用了。比如我们经常用的数...

程序员阿康 486

Java的ServiceLoader:实现自定义SPI时,服务提供者的注册机制

大家好,今天我们来深入探讨Java ServiceLoader,特别是围绕着自定义SPI(Service Provider Interface)的实现,以及服务提供者的注册机制进行详细讲解。ServiceLoader是Java提供的一种服务发现机制,它允许我们在运行时动态地加载服务实现,而无需在编译时硬编码依赖关系。这极大地提高了代码的灵活性和可扩展性。1. SPI的概念与意义。

weixin_41455464的博客 1125

java用来模块化开发和扩展很有用的服务加载器 ServiceLoader类实现SPI机制

`java.util.ServiceLoader` 是Java中用于实现服务提供者接口(Service Provider Interface, SPI)机制的一个工具。SPI允许你在不修改现有代码的情况下,动态地加载和使用第三方实现。这在插件化设计、模块化开发和扩展性需求中非常有用。

爱的叹息的专栏 635

JDK java.util.ServiceLoader SPI 扩展机制

博文目录 文章目录SPISPI简单应用 Java SPI详解 SPI SPI全称 Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。 API (Application Programming Interface)在大多数情况下,都是实现方制定接口并完成对接口的实现,调用方仅仅依赖接口调用,且无权选择不同实现。 从使用人员上来说,API 直接被应用开发人员使用。

mrathena 443

Java SPI 机制实战:用 ServiceLoader 写出可插拔的扩展点

你有没有遇到过这种需求:核心代码里有一个「支付渠道」「文件解析器」「短信通道」之类的接口,现在要接第三个、第四个实现,结果每加一个就得回去改一次工厂类的switch,还得重新编译打包核心模块。业务方想自己塞一个实现进来?对不起,请给核心模块提 PR。这就是典型的「扩展点写死在核心里」。JDK 自带的 SPI(Service Provider Interface)+就是来解决这个的:核心只定义接口,实现方把自己的实现「声明」在一个约定文件里,运行时自动被发现、加载。JDBC 的Driver。

weixin_42662753的博客 178
上一篇: web 登录验证 xss csrf 跨域请求
下一篇: Apache 配置 WebSocket 协议
conquer0715
博客等级 码龄18年 73粉丝 147原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值