一、概念
多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。提供者为框架的用户提供了多个API实现,框架必须提供一种机制来注册这些实现以便用户能够使用它们;框架的客户直接使用API,无需关心自己到底在使用哪个实现。
服务接口(Service Interface):定义了抽象的服务,以及一个或多个方法
服务实现类(Service Interface Impl):实现服务接口,实现具体的方法
服务提供者接口(Service Provider Interface):定义了抽象的服务提供者,提供一个获取服务的方法
服务提供者实现类(Service Provider Interface Impl):实现服务提供者接口,实现具体的方法
服务提供者注册API(Provider Registration API):提供一个注册服务提供者接口
服务访问API(Service Access API):提供一个调用服务的方法,是客户端用来获取服务的实例的
二、例子
服务接口(Service Interface)
/**
* 服务者接口
*/
public interface IService {
/**
* 实现方法doService()
*/
void doService();
/**
* 实现方法doServiceTest
*/
void doServiceTest();
}
服务实现类(Service Interface Impl)
/**
* 服务者接口实现类
*/
public class ServiceImpl implements IService {
/**
* 实现方法doService
*/
public void doService() {
System.out.println("do service ...");
}
/**
* 实现方法doServiceTest
*/
public void doServiceTest() {
System.out.println("do service test ...");
}
}
服务提供者接口(Service Provider Interface)
/**
* 提供者接口
*/
public interface IProvider {
/**
*
* 关联IService,用来获取服务者接口
*/
public IService getService();
}
服务提供者实现类(Service Provider Interface Impl)
/**
* 提供者接口的实现类
*/
public class ProviderImpl implements IProvider {
/**
* 实现静态的注册
*/
private static final String DEFAULT_PROVIDER = "test";
static {
ServiceManager.registerProvider(DEFAULT_PROVIDER, new ProviderImpl());
}
/**
* 关联IService,用来获取服务接口
*/
public IService getService() {
return new ServiceImpl();
}
}
服务提供者注册API(Provider Registration API)& 服务访问API(Service Access API)
/**
* 服务提供者管理类
*/
public class ServiceManager {
private ServiceManager() {
}
private static final Map<String, IProvider> providers = new ConcurrentHashMap<String, IProvider>();
/**
* 服务提供者注册API,注册服务提供者接口
*/
public static void registerProvider(String name, IProvider p) {
providers.put(name, p);
}
/**
* 服务访问API,通过提供者来获取服务者接口
*/
public static IService getService(String name) {
IProvider p = providers.get(name);
if (p == null) {
throw new IllegalArgumentException(
"No provider registered with name:" + name);
}
return p.getService();
}
}
客户端测试类
/**
* 客户端测试类
*/
public class Client {
/**
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.lzw.provider.impl.ProviderImpl");
IService service = ServiceManager.getService("test");
service.doService();
service.doServiceTest();
}
}
三、数据库驱动服务提供者
服务接口(Service Interface)
public interface Connection extends Wrapper, AutoCloseable {
Statement createStatement() throws SQLException;
PreparedStatement prepareStatement(String sql)
throws SQLException;
.......省略其他代码.......
}
服务实现类(Service Interface Impl)
package com.mysql.jdbc;
public class ConnectionImpl extends ConnectionPropertiesImpl implements MySQLConnection {
public java.sql.Statement createStatement() throws SQLException {
return this.createStatement(1003, 1007);
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
return this.prepareStatement(sql, 1003, 1007);
}
.......省略其他代码.......
}
服务提供者接口(Service Provider Interface)
public interface Driver {
Connection connect(String url, java.util.Properties info)
throws SQLException;
boolean acceptsURL(String url) throws SQLException;
.......省略其他代码.......
}
服务提供者实现类(Service Provider Interface Impl)
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!");
}
}
public Connection connect(String url, Properties info) throws SQLException {
if (url == null) {
throw SQLError.createSQLException(Messages.getString("NonRegisteringDriver.1"), "08001", (ExceptionInterceptor)null);
} else if (StringUtils.startsWithIgnoreCase(url, "jdbc:mysql:loadbalance://")) {
return this.connectLoadBalanced(url, info);
} else if (StringUtils.startsWithIgnoreCase(url, "jdbc:mysql:replication://")) {
return this.connectReplicationConnection(url, info);
} else {
Properties props = null;
if ((props = this.parseURL(url, info)) == null) {
return null;
} else if (!"1".equals(props.getProperty("NUM_HOSTS"))) {
return this.connectFailover(url, info);
} else {
try {
com.mysql.jdbc.Connection newConn = ConnectionImpl.getInstance(this.host(props), this.port(props), props, this.database(props), url);
return newConn;
} catch (SQLException var6) {
throw var6;
} catch (Exception var7) {
SQLException sqlEx = SQLError.createSQLException(Messages.getString("NonRegisteringDriver.17") + var7.toString() + Messages.getString("NonRegisteringDriver.18"), "08001", (ExceptionInterceptor)null);
sqlEx.initCause(var7);
throw sqlEx;
}
}
}
}
}
服务提供者注册API(Provider Registration API)& 服务访问API(Service Access API)
public class DriverManager {
// 服务提供者信息列表
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
private DriverManager(){}
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
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;
}
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
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);
}
}
}
/**
* 服务提供者注册API
*/
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
registerDriver(driver, null);
}
/**
* 服务访问API
*/
@CallerSensitive
public static Connection getConnection(String url,
java.util.Properties info) throws SQLException {
return (getConnection(url, info, Reflection.getCallerClass()));
}
}
四、附件
ServiceLoader源码分析可以看我另一篇文章:juejin.cn/post/684490…