首先引用API中的说明文档:
一个简单的服务提供者加载设施。
服务
是一个熟知的接口和类(通常为抽象类)集合。服务提供者
是服务的特定实现。提供者中的类通常实现接口,并子类化在服务本身中定义的子类。服务提供者可以以扩展的形式安装在 Java 平台的实现中,也就是将 jar
文件放入任意常用的扩展目录中。也可通过将提供者加入应用程序类路径,或者通过其他某些特定于平台的方式使其可用。
为了加载,服务由单个类型表示,也就是单个接口或抽象类。(可以使用具体类,但建议不要这样做。)一个给定服务的提供者包含一个或多个具体类,这些类扩展了此服务类型
,具有特定于提供者的数据和代码。提供者类
通常不是整个提供者本身而是一个代理,它包含足够的信息来决定提供者是否能满足特定请求,还包含可以根据需要创建实际提供者的代码。提供者类的详细信息高度特定于服务;任何单个类或接口都不能统一它们,因此这里没有定义任何这种类型。此设施唯一强制要求的是,提供者类必须具有不带参数的构造方法,以便它们可以在加载中被实例化。
通过在资源目录 META-INF/services
中放置提供者配置文件
来标识服务提供者。文件名称是服务类型的完全限定
二进制名称
。该文件包含一个具体提供者类的完全限定二进制名称列表,每行一个。忽略各名称周围的空格、制表符和空行。注释字符为
'#'
('\u0023'
, NUMBER
SIGN
);忽略每行第一个注释字符后面的所有字符。文件必须使用 UTF-8 编码。
....还有其他的一些就不拷贝过来了。
从说明中可以看出,这个机制允许服务的声明与实现的分离,具体使用哪个实现可以在运行时才决定,使用哪个实现取决于是否部署了该实现。下面是个简单的demo。
1、首先定义一个表示服务的接口:
package learn.serviceLoader.service;
import java.util.ServiceLoader;
public abstract class SimpleService {
public abstract void doService();
private static boolean isInit = false;
private static SimpleService service = null;
public static final SimpleService getService() {
if (!isInit) {
ServiceLoader<SimpleService> serviceLoader = ServiceLoader
.load(SimpleService.class);
for (SimpleService s : serviceLoader) {
service = s;
break;
}
isInit = true;
}
return service;
}
}
此接口定义了服务的能力,同时提供了工厂方法来获取服务的实例。这个工厂方法就是通过此机制来查找服务的实现的。
2、实现服务提供者。
package learn.serviceLoader.serviceimpl;
import learn.serviceLoader.service.SimpleService;
public class StandarService extends SimpleService {
@Override
public void doService() {
System.out
.println("i am standar service, i implement SimpleService, so you get here .");
}
}
就是实现服务接口的方法。
3、在服务提供者jar中下配置:
a、建立一个META-INF文件夹,在META-INF文件夹下建立一个services文件夹;
b、在services文件夹下建立服务配置文件,如:learn.serviceloader.service.SimpleService
里面的内容就是提供者的全限定类名:learn.serviceLoader.serviceimpl.StandarService # comment
4、服务的使用者:
package learn.serviceLoader.test;
import learn.serviceLoader.service.SimpleService;
public class TestServiceLoader {
public static void main(String[] args) {
SimpleService service = SimpleService.getService();
service.doService();
SimpleService service2 = SimpleService.getService();
service2.doService();
}
}
服务的使用者通过服务接口的工厂方法来获取服务,使用者并不知道、也不需要知道使用的是哪个服务提供者。
对于复杂的使用,应该将服务的声明放在单独的api.jar包,不同的实现放在不同的jar,部署时只需要部署api.jar和特定的提供者jar包。此机制还支持 “reload
()
清除此加载器的服务者缓存,以重载所有服务者。”,应该可以预留方法,实现动态切换服务提供者。
这是个简单又强大的机制,可以方便地实现服务声明与实现的分离。
分享到:
相关推荐
提供spidemo.cloud.CloudService实用程序类来包装java.util.ServiceLoader操作。 搜索服务 演示伪“关键字搜索服务”提供程序。 为服务提供者定义spidemo.search.spi.Search接口。 提供spidemo.search.Search...
综上所述,"spi-Demo.rar"中的内容可能包括一个展示了如何定义服务接口、创建服务提供者、编写配置文件以及如何在应用中使用`ServiceLoader`加载服务的示例代码。通过这个Demo,学习者可以更好地理解和掌握Java SPI...
3. **服务加载器**:Java SPI提供了`java.util.ServiceLoader`类,用于加载配置文件中的服务提供者,并实例化这些类。 ### 二、SPI工作流程 1. **查找配置文件**:`ServiceLoader`会去`META-INF/services`目录下...
这个机制在Java中主要由`java.util.ServiceLoader`类来实现。在本示例中,我们将探讨如何创建一个简单的SPI入门级Demo,具体是关于实现一个加法服务。 首先,理解SPI的基本流程: 1. **定义接口**:服务接口是所有...
4. **加载服务**:使用`java.util.ServiceLoader`类来加载并实例化服务提供者。`ServiceLoader`会自动读取服务配置文件,并创建每个服务提供者的实例。 ```java ServiceLoader<Plugin> loader = ServiceLoader.load...
4. **服务加载**:在程序中,我们可以通过`java.util.ServiceLoader`类来加载并使用SPI服务。下面是一个简单的加载和使用SPI服务的示例: ```java import java.util.ServiceLoader; public class SPIConsumer { ...
在Java中,SPI的核心接口位于`java.util.ServiceLoader`类中。它提供了一种通过读取`META-INF/services/`目录下的配置文件来查找并加载服务提供商的方法。下面我们将详细介绍如何使用SPI,并给出示例代码。 首先,...
在java.util.ServiceLoader的文档里有比较详细的介绍。究其思想,其实是和"Callback"差不多。“Callback”的思想是在我们调用API的时候,我们可以自己写一段逻辑代码,传入到API里面,API内部在合适的时候会调用它,...
- `java.util.Properties`:用来存储配置信息,这里没有实际使用。 2. **获取数据库连接** - 使用`Class.forName()`方法加载指定的JDBC驱动。这里的`com.mysql.jdbc.Driver`是MySQL JDBC驱动的类名。 - 使用`...
在`java.util.ServiceLoader`类的帮助下,我们可以方便地加载并使用这些服务提供者。下面我们将详细探讨Java SPI的工作原理、如何创建和使用SPI服务,以及一个具体的`SpiDemo`实例。 1. **SPI工作原理** - **配置...
SPI机制的核心是`java.util.ServiceLoader`类,它允许我们按照约定在`META-INF/services`目录下创建配置文件,来指定哪些类实现了特定的服务接口。 服务接口定义:在SPI机制中,首先我们需要定义一个服务接口,这个...
在Java中,SPI主要通过`java.util.ServiceLoader`类来实现。 在描述中提到了一个博客链接,虽然具体内容没有提供,但我们可以假设这个博客详细解释了如何创建和使用SPI的示例。通常,SPI的实现包括以下几个步骤: ...
2. **ServiceLoader**:Java的`java.util.ServiceLoader` 类是实现SPI的关键。它提供了一种迭代方式来加载服务提供者。通过`ServiceLoader.load()`方法,我们可以加载符合特定接口的所有实现。 3. **接口与实现**:...
首先,SPI的核心在于`java.util.ServiceLoader`类,它是Java SPI的入口点。通过这个类,我们可以方便地加载实现了指定接口的各个服务提供商。在SPI中,契约通常指的是接口,它定义了服务提供商必须遵循的行为规范。 ...
java.util.ServiceLoader首先实现了Iterable接口,所以它有迭代器的属性,这里主要都是实现了迭代器的hasNext和next方法。这里主要都是调用的lookupIterator的相应hasNext和next方法,lookupIterator是懒加载迭代器...
JDK SPI的核心类是`java.util.ServiceLoader`,它负责加载`META-INF/services/`目录下对应接口名称的配置文件,并根据配置文件中的类名创建服务实现的实例。配置文件的格式通常是每行一个类名,这些类实现了指定的...