小明学java基础系列——Java SPI机制

本文详细介绍了Java的Service Provider Interface(SPI)机制,包括SPI与API的区别、优点,以及SPI的约定,如模块化语句和配置文件的使用。通过实例展示了在模块化和非模块化环境下如何实现SPI,并探讨了SPI的加载原理,如类限定名获取、类加载器的工作方式以及ServiceLoader的使用。最后,文章提到了在加载过程中可能遇到的网络资源问题和解决方案。
摘要由CSDN通过智能技术生成

一、SPI机制介绍

SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。

1.1 SPI和API的区别

API (Application Programming Interface)在大多数情况下,都是实现方制定接口并完成对接口的实现,调用方仅仅依赖接口调用,且无权选择不同实现。 从使用人员上来说,API 直接被应用开发人员使用。如下图所示,其中模块A为接口制定方和实现方,而模块B为接口的使用放。
在这里插入图片描述

维基百科关于API的描述:In building applications, an API (application programming interface) simplifies programming by abstracting the underlying implementation and only exposing objects or actions the developer needs. While a graphical interface for an email client might provide a user with a button that performs all the steps for fetching and highlighting new emails, an API for file input/output might give the developer a function that copies a file from one location to another without requiring that the developer understand the file system operations occurring behind the scenes.

SPI (Service Provider Interface)是调用方来制定接口规范,提供给外部来实现,调用方在调用时则选择自己需要的外部实现,可用于启用框架扩展和可替换组件。 从使用人员上来说,SPI 被框架扩展人员使用。如下图所示,A模块是接口的定义方和使用方,而B模块则是接口实现方。
在这里插入图片描述

SPI 维基百科定义:Service Provider Interface (SPI) is an API intended to be implemented or extended by a third party. It can be used to enable framework extension and replaceable components

SPI java官方定义:A service is a well-known set of interfaces and (usually abstract) classes. A service provider(SPI) is a specific implementation of a service. The classes in a provider typically implement the interfaces and subclass the classes defined in the service itself. Service providers can be installed in an implementation of the Java platform in the form of extensions, that is, jar files placed into any of the usual extension directories. Providers can also be made available by adding them to the application’s class path or by some other platform-specific means.

1.2 SPI的优点

使用 Java SPI 机制的优势是实现解耦,使得接口的定义与具体业务实现分离,而不是耦合在一起。应用进程可以根据实际业务情况启用或替换具体组件。以java中的JDBC数据库驱动为例,java官方在核心库制定了java.sql.Driver数据库驱动接口,使用该接口实现了数据库链接等逻辑,但是并没有具体实现数据库驱动接口,而是交给MySql等厂商去实现具体的数据库接口。

引用自博客:Java SPI 主要是应用于厂商自定义组件或插件中。在java.util.ServiceLoader的文档里有比较详细的介绍。简单的总结下java SPI机制的思想:我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块、xml解析模块、jdbc模块等方案。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 Java SPI就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。

二、SPI的约定

服务提供方需要通过一些约定告诉系统自己所提供的服务的位置,java9之后一共有两种约定方式:

  1. 通过在META-INF/services/ 目录下配置相关文件实现。
  2. 通过java9 jigsaw的导出语句指定服务位置。

A service provider is a single type, usually a concrete class. An interface or abstract class is permitted because it may declare a static provider method, discussed later. The type must be public and must not be an inner class.
A service provider and its supporting code may be developed in a module, which is then deployed on the application module path or in a modular image. Alternatively, a service provider and its supporting code may be packaged as a JAR file and deployed on the application class path. The advantage of developing a service provider in a module is that the provider can be fully encapsulated to hide all details of its implementation.
An application that obtains a service loader for a given service is indifferent to whether providers of the service are deployed in modules or packaged as JAR files. The application instantiates service providers via the service loader’s iterator, or via Provider objects in the service loader’s stream, without knowledge of the service providers’ locations.

2.1 模块化语句约定

模块化语句约定适用于项目已经模块化的情况,以java.sql.Driver为例,在模块化文件module-info.java中添加如下语句,就可以向应用提供指定的服务:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-御狐神-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值