JAVA使用ServiceLoader加载服务

JAVA使用ServiceLoader加载服务

https://blog.csdn.net/jianggujin/article/details/81030983

serviceLoader就是spi的一种实现,spi服务的提供者接口也就是spi service provider  interface

主要是创建一个接口让第三方框架去实现,比如jdbc.driver这个可以被mysql,oracle,SQLServer去实现

还有像日志logger,有slf4j

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/jianggujin/article/details/81030983
ServiceLoader是SPI的是一种实现,所谓SPI,即Service Provider Interface,用于一些服务提供给第三方实现或者扩展,可以增强框架的扩展或者替换一些组件。
其实关于ServiceLoader,我们平时虽然很少用到,但是却在背后为我们做了很多事情,最常见的就是JDBC的操作了,相信大家对DriverManager类并不陌生,我们可以通过该类加载驱动并获得数据库连接,在这个类中其实就用到了ServiceLoader。

private static void loadInitialDrivers() {
String drivers;
try {
drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("jdbc.drivers");
}
});
} catch (Exception ex) {
drivers = null;
}
// If the driver is packaged as a Service Provider, load it.
// Get all the drivers through the classloader
// exposed as a java.sql.Driver.class service.
// ServiceLoader.load() replaces the sun.misc.Providers()

AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {

ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();

/* Load these drivers, so that they can be instantiated.
* It may be the case that the driver class may not be there
* i.e. there may be a packaged driver with the service class
* as implementation of java.sql.Driver but the actual class
* may be missing. In that case a java.util.ServiceConfigurationError
* will be thrown at runtime by the VM trying to locate
* and load the service.
*
* Adding a try catch block to catch those runtime errors
* if driver not available in classpath but it's
* packaged as service and that service is there in classpath.
*/
try{
while(driversIterator.hasNext()) {
driversIterator.next();
}
} catch(Throwable t) {
// Do nothing
}
return null;
}
});

println("DriverManager.initialize: jdbc.drivers = " + drivers);

if (drivers == null || drivers.equals("")) {
return;
}
String[] driversList = drivers.split(":");
println("number of Drivers:" + driversList.length);
for (String aDriver : driversList) {
try {
println("DriverManager.Initialize: loading " + aDriver);
Class.forName(aDriver, true,
ClassLoader.getSystemClassLoader());
} catch (Exception ex) {
println("DriverManager.Initialize: load failed: " + ex);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
接下来我们就还看看如何使用ServiceLoader,假设我们需要一个日志的服务,那么首先我们需要定义一个服务的接口

package com.jinggujin.service;

public interface LogService {
void log(String msg);
}
1
2
3
4
5
针对这个服务我们再来提供一个实现

package com.jinggujin.service;

public class DefaultLogService implements LogService {

@Override
public void log(String msg) {
System.out.println(msg);
}
}
1
2
3
4
5
6
7
8
9
好了下面我们需要提供我们的服务,我们需要在META-INF中添加services文件夹,然后在该文件夹中创建一个文件,文件名为服务接口的全限定类名,那么这里完整的文件路径应为:META-INF/services/com.jinggujin.service.LogService,最后我们需要在该文件中添加服务实现的全限定类名,一行数据一个实现全限定类名,文件内容如下:

com.jinggujin.service.DefaultLogService
1
准备工作已经完成,我们就来使用ServiceLoader加载我们提供的服务。

package test;

import java.util.ServiceLoader;

import org.junit.Test;

import com.jinggujin.service.LogService;

public class ServiceLoaderTest {
@Test
public void test() {
ServiceLoader<LogService> loader = ServiceLoader.load(LogService.class);

for (LogService service : loader) {
System.out.println(service.getClass());
}
}
}
---------------------
作者:蒋固金
来源:CSDN
原文:https://blog.csdn.net/jianggujin/article/details/81030983
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/handsome1013/p/9946855.html