Java SPI的介绍、JDBC中SPI的应用、自己实现一个SPI应用

news2024/11/10 7:49:48

目录

  • 1. Java SPI介绍
  • 2. Java SPI的运行流程
  • 3. Java SPI在JDBC中的应用
  • 4. Java SPI的三大规范要素
  • 5. 自己实现一个SPI应用
    • 5.1 Service接口
    • 5.2 运营商1的Service Provider
    • 5.3 运营商2的Service Provider
    • 5.3 手机使用网络

1. Java SPI介绍

SPI(Service Provider Interface)是一种基于ClassLoader来发现并加载服务的机制。用于实现各种插件或灵活替换框架所使用的组件。设计思想采用:面向接口 + 配置文件 + 反射技术

一个标准的SPI,由以下3部分构成:

  • Service:一个公开的接口或抽象类,定义了一个抽象的功能模块
  • Service Provider:Service接口的一个实现类
  • ServiceLoader:是SPI机制中的核心组件,负责在运行时发现并加载Service Provider

优点:基于面向接口编程,实现了模块之间的解耦

应用场景:JDBC、slf4j、Servlet容器初始化等

2. Java SPI的运行流程

Java SPI的运行流程

3. Java SPI在JDBC中的应用

JDBC(Java DataBase Connectivity)是Java语言来访问数据库的一套API,每个数据库厂商都会提供各自的JDBC实现

JDBC访问

以前我们使用JDBC访问Mysql数据库的时候,都会执行Class.forName("com.mysql.cj.jdbc.Driver"),这样就会实例化驱动类,同时也会执行驱动类中的static代码块中的DriverManager.registerDriver(new Driver()),将驱动类注册到Drivermanager中

但是将驱动类的全路径名称写到代码中,非常不方便。如果将类的全路径名写到配置文件中,虽然方便,但是还需要我们去记驱动类的全路径名

使用Java的SPI就可以解决这个问题。让Mysql驱动提供方同时提供驱动包和驱动配置文件,Java SPI通过类ClassLoader(通过getResource/getResources从指定位置读取classpath中的配置文件、可以加载类)自动从指定位置读取配置文件并进行驱动类的加载。这样就不用我们进行驱动类的加载了,而且Mysql驱动提供方能很方便的进行驱动的升级

4. Java SPI的三大规范要素

  1. Service Provider类必须具备无参的默认构造方法

因为会通过反射技术实例化Service Provider,是不带参数的

Mysql的驱动类实现如下:

package com.mysql.cj.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}
  1. 规范的配置文件
  • 配置文件路径:必须在jar包中的META-INF/services目录下
  • 配置文件名称:Service接口的全路径名
  • 配置文件内容:Service Provider类的全路径名。如果有Service实现类(Service Provider类),那么每一个Service Provider类的全路径名在文件中单独占一行

Mysql驱动的配置文件如下所示:

Mysql的驱动配置文件

  1. 保证能加载到配置文件和Service Provider类
  • 方式一:将Service Provider的jar包放到classpath中。该方式最常用,通过maven引入依赖也是这种方式。程序运行时自动加载配置文件和Service Provider类。虽然能加载Service Provider类,但是不能引用Service Provider类,可以参考Mysql的驱动类进行注册获取Service Provider类的引用
  • 方式二:将Service Provider的jar包放到jre的扩展目录中。程序运行时自动加载配置文件和Service Provider类。虽然能加载Service Provider类,但是不能引用Service Provider类,可以参考Mysql的驱动类进行注册获取Service Provider类的引用
  • 方式三:自定义一个ClassLoader。需要我们自己在程序中实现。程序运行时自动加载配置文件和Service Provider类。这种方式不但能加载Service Provider类,还能获取到Service Provider类

5. 自己实现一个SPI应用

应用背景:手机需要连接网络,定义一个连接网络的Service接口。由运营商1和运营商2实现Service接口来提供具体的网络服务

我们先在IDEA创建一个项目javaSpiTest

5.1 Service接口

在项目下面创建一个module,名称为network。定义一个NetworkService接口,内容如下:

package com.hh.network;

public interface NetworkService {

    void connectNetwork();
}

5.2 运营商1的Service Provider

在项目下面创建一个module,名称为operator1,依赖module network。定义一个BeijingNetworkServiceProvider类,内容如下:

package com.hh.operator1;

import com.hh.network.NetworkService;

import java.io.UnsupportedEncodingException;

public class BeijingNetworkServiceProvider implements NetworkService {

    @Override
    public void connectNetwork() {

        try {
            System.out.println(
                    new String("operator1提供的北京网络".getBytes(), "UTF-8")
            );
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

    }
}

再定义一个ShanghaiNetworkServiceProvider类,内容如下:

package com.hh.operator1;

import com.hh.network.NetworkService;

import java.io.UnsupportedEncodingException;

public class ShanghaiNetworkServiceProvider implements NetworkService {

    @Override
    public void connectNetwork() {

        try {
            System.out.println(
                    new String("operator1提供的上海网络".getBytes(), "UTF-8")
            );
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

    }
}

配置文件:在resources目录下新建文件META-INF/services/com.hh.network.NetworkService,内容如下:

com.hh.operator1.BeijingNetworkServiceProvider
com.hh.operator1.ShanghaiNetworkServiceProvider

5.3 运营商2的Service Provider

在项目下面创建一个module,名称为operator2,依赖module network。定义一个GuangzhouNetworkServiceProvider类,内容如下:

package com.hh.operator2;

import com.hh.network.NetworkService;

import java.io.UnsupportedEncodingException;

public class GuangzhouNetworkServiceProvider implements NetworkService {

    @Override
    public void connectNetwork() {

        try {
            System.out.println(
                    new String("operator2提供的广州网络".getBytes(), "UTF-8")
            );
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

    }
}

配置文件:在resources目录下新建文件META-INF/services/com.hh.network.NetworkService,内容如下:

com.hh.operator2.GuangzhouNetworkServiceProvider

5.3 手机使用网络

在项目下面创建一个module,名称为phone,依赖module operator1。定义一个PhoneNetworkUse类,内容如下:

package com.hh.phone;

import com.hh.network.NetworkService;

import java.util.ServiceLoader;

public class PhoneNetworkUse {

    public static void main(String[] args) {

        ServiceLoader<NetworkService> serviceLoader =
                ServiceLoader.load(NetworkService.class);

        for(NetworkService networkService: serviceLoader) {
            networkService.connectNetwork();
        }

    }
}

运行程序,结果如下:

operator1提供的北京网络
operator1提供的上海网络

如果将依赖module operator1,改成依赖module operator2。再运行程序,结果如下:

operator2提供的广州网络

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

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

相关文章

在别墅大宅中打造全屋智能,总共需要几步?

关于智能家居&#xff0c;很多读者可能会想起一些不那么愉快的回忆&#xff1a;2014年左右的智能家居浪潮&#xff0c;涌现出了众多带蓝牙互联功能的家电产品&#xff0c;但数据无法互联互通、单品体验升级有限&#xff0c;加上一些企业竞争失败产品不再更新&#xff0c;留给消…

EXCEL工具介绍

目录1. 锁定功能2. 固定1. 锁定功能 锁定&#xff1a;F4 公式引用单元格&#xff0c;有“相对引用”与“绝对引用” 美元符号“ $ ”在excel公式中的作用是在“绝对引用”时&#xff0c;锁定行号或列标&#xff08;单元格地址由列标行号组成&#xff0c;如A1&#xff0c;A为列…

国产软件不惧微软,WPS力扛大旗,新型办公软件争相助力

金山作为程序员的“黄埔军校”&#xff0c;输入了一批批互联网大佬&#xff0c;小米的雷军、哔哩哔哩的陈睿、蓝港互动的王峰等都师出金山。WPS作为金山拳头作品&#xff0c;有着“国民软件”美誉&#xff0c;功能强大&#xff0c;使用体验一点不输微软word&#xff0c;然而有一…

打工人必学的法律知识(三)——《中华人民共和国劳动争议调解仲裁法》

PS &#xff1a; 对与日常工作比较紧密的部分做摘录 中华人民共和国劳动争议调解仲裁法http://www.npc.gov.cn/npc/c198/200712/756d4eceb95e420a87c97545a58d931c.shtml 目录 一、调解 二、仲裁 三、申请和受理 四、开庭和裁决 五、附则 第六条 发生劳动争议&#xff0…

python镜像设置

winr 输入 %USERPROFILE% 新建pip目录&#xff0c;目录内新建pip.ini 输入&#xff1a; [global] index-urlhttp://mirrors.aliyun.com/pypi/simple/ trusted-hostmirrors.aliyun.com

计算机网络概括

1 前言计算机网络是指将位于不同地理位置&#xff0c;但具有独立功能的多台设备&#xff0c;通过通信设备和线路连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件、网络通信协议的协调管理下&#xff0c;实现资源共享和信息传递的计算机系统。简单来说&#xff0c;…

STM32模拟SPI总线读写RFID模块RC522

STM32模拟SPI总线读写RFID模块RC522 RC522是一款NXP 公司的支持ISO14443A协议的高频&#xff08;13.56MHz&#xff09;RFID射频芯片。RFID有ID和IC两种卡应用类型&#xff0c;RC522属于IC卡的应用类型。NFC则属于增强的IC卡类型&#xff0c;支持双向通信和更多类型的协议。 I…

es官网翻译之Exploring Your Cluster

Exploring Your Cluster 探索你的集群 The rest api rest 风格的 api Now that we have our node (and cluster) up and running, the next step is to understand how to 现在 我们已经将我们自己的节点(和集群) 启动并运行着, 下一个步骤是知道如何 communicate with it…

Java面试题每日10问(12)

1. What is String Pool? String pool is the space reserved in the heap memory that can be used to store the strings.The main advantage of using the String pool is whenever we create a string literal; the JVM checks the “string constant pool” first.If th…

速度为单GPU1.6倍,kaggle双GPU(ddp模式)加速pytorch攻略

accelerate 是huggingface开源的一个方便将pytorch模型迁移到 GPU/multi-GPUs/TPU/fp16 模式下训练的小巧工具。和标准的 pytorch 方法相比&#xff0c;使用accelerate 进行多GPU DDP模式/TPU/fp16 训练你的模型变得非常简单(只需要在标准的pytorch训练代码中改动不几行代码就可…

linux基功系列之man帮助命令实战

文章目录前言一、man命令介绍二、常用参数2.1 语法2.2 常用参数2.3 man页面的操作命令man命令使用案例1. 直接查看手册2. -aw 参数找到可以被查询的章节2.3 一次性查阅所有章节2.4 搜索手册页2.5 -L 设置查询语言总结前言 linux系统中的命令数量有上千的&#xff0c;即使是常用…

前端——周总结系列二

1 JS数组排序sort()方法 不传参数排序&#xff0c;默认根据Unicode排序 附录 传参数&#xff0c;使用比较函数&#xff0c;自己定义比较规则 简单数组排序 // 升序 function ascSort(a, b) {return a - b; } // 降序 function ascSort(a, b) {return b - a; }数组对象排序…

算法leetcode|31. 下一个排列(rust重拳出击)

文章目录31. 下一个排列&#xff1a;样例 1&#xff1a;样例 2&#xff1a;样例 3&#xff1a;提示&#xff1a;分析&#xff1a;题解&#xff1a;rustgoccpythonjava31. 下一个排列&#xff1a; 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0…

ROS2机器人编程简述humble-第二章-First Steps with ROS2 .1

ROS2机器人编程简述新书推荐-A Concise Introduction to Robot Programming with ROS2学习笔记流水账-推荐阅读原书。第二章主要就是一些ROS的基本概念&#xff0c;其实ROS1和ROS2的基本概念很多都是类似的。ROS2机器人个人教程博客汇总&#xff08;2021共6套&#xff09;如何更…

Linux chgrp 命令

Linux chgrp&#xff08;英文全拼&#xff1a;change group&#xff09;命令用于变更文件或目录的所属群组。与 chown 命令不同&#xff0c;chgrp 允许普通用户改变文件所属的组&#xff0c;只要该用户是该组的一员。在 UNIX 系统家族里&#xff0c;文件或目录权限的掌控以拥有…

(一)Jenkins部署、基础配置

目录 1、前言 1.1、Jenkins是什么 1.2、jenkins有什么用 2、 Jenkins安装 2.1、jdk安装 2.2、安装Jenkins 3、Jenkins配置 3.1、解锁Jenkins 3.2、插件安装 3.3、创建管理员 3.4、实例配置 4、汉化 4.1、下载Locale插件 4.2、设置为中文 5、设置中文失效解决步骤 1…

U-Boot 之零 源码文件、启动阶段(TPL、SPL)、FALCON、设备树

最近&#xff0c;工作重心要从裸机开发转移到嵌入式 Linux 系统开发&#xff0c;在之前的博文 Linux 之八 完整嵌入式 Linux 环境、&#xff08;交叉&#xff09;编译工具链、CPU 体系架构、嵌入式系统构建工具 中详细介绍了嵌入式 Linux 环境&#xff0c;接下来就是重点学习一…

【Spring6源码・AOP】代理对象的创建

前三篇Spring IOC的源码解析与这一章的AOP是紧密相连的&#xff1a; 【Spring6源码・IOC】BeanDefinition的加载 【Spring6源码・IOC】Bean的实例化 【Spring6源码・IOC】Bean的初始化 - 终结篇 首先介绍我们本章的demo&#xff1a; 一个接口&#xff0c;一个实现&#xf…

【论文速递】ECCV2022 - 开销聚合与四维卷积Swin Transformer_小样本分割

【论文速递】ECCV2022 - 开销聚合与四维卷积Swin Transformer_小样本分割 【论文原文】&#xff1a;Cost Aggregation with 4D Convolutional Swin Transformer for Few-Shot Segmentation 获取地址&#xff1a;https://arxiv.org/pdf/2207.10866.pdf博主关键词&#xff1a; …

紧聚焦涡旋光束app设计-VVB2.0

紧聚焦涡旋光束app设计-VVB2.0前言界面预览功能演示写在最后前言 时隔几个月&#xff0c;花了点时间&#xff0c;将之前用matlab设计的app紧聚焦涡旋光束matlab gui设计进行一次修改&#xff0c;这次发布2.0版本&#xff0c;本次修改的范围主要是将原来的界面进行重做&#xf…