通过JDBC了解服务提供者框架
这篇博客引用了一些《Effective Java》书中的内容
一.服务提供者框架组成及作用
- 服务接口(Server Interface)
- 提供者注册API(Service Registration API)
- 服务提供者接口(Service Provider Interface)
- 服务访问API(Service Acess API)
作用:
- 服务接口:定义了提供哪些服务
- 提供者注册API:注册提供者
- 服务提供者接口:返回一个实现了服务接口的类的实例
-
服务访问API:在注册过的所有提供者中寻找合适的提供者,然后调用该提供者的方法,返回一个实现了服务接口的对象
//服务接口 public interface Service{ //...服务所调用的方法声明 } //服务提供者接口 public interface Provider{ //返回服务接口的实现类的实例 Service newService(); } public class Services{ private Services() {} private static final Map<String, Provider> providers = new ConcurrentHasMap<String, Provider>(); //服务提供者注册API public static void registerProvider(String name, Provider p) { providers.put(name, p) } //服务访问API public static Service getService(String name) { Provider p = providers.get(name); if(p != null) return p.newService(); } } //服务接口的实现类 public class ServiceImpl implements Service{ //实现接口中的所有服务 } //服务提供者接口的实现类 public class ProviderImpl implements Provider{ //返回服务接口的实现类的实例 public Service newService() { return new ServiceImpl(); } }
对应的UML图如下:
二.简单分析JDBC
首先看源码(删减部分代码)
public interface Connection extends Wrapper, AutoCloseable {
Statement createStatement() throws SQLException;
PreparedStatement prepareStatement(String sql)
throws SQLException;
}
上述代码为java.sql.Connection的部分源码,在服务提供者框架中,扮演着Service(服务接口)的角色。
public interface Driver {
//这个方法返回java.sql.Connection(服务接口)
Connection connect(String url, java.util.Properties info)
throws SQLException;
}
上述代码为java.sql.Driver的部分源码,在服务提供者框架中,扮演者Provider(服务提供者接口)的角色
public class DriverManager {
private final static CopyOnWriteArrayList<DriverInfo>
registeredDrivers = new CopyOnWriteArrayList<>();
private DriverManager(){}
//服务提供者注册API
public static synchronized void registerDriver(java.sql.Driver driver,
DriverAction da)
throws SQLException {
if(driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
throw new NullPointerException();
}
//服务访问API
public static Connection getConnection(String url)
throws SQLException {
java.util.Properties info = new java.util.Properties();
return (getConnection(url, info, Reflection.getCallerClass()));
}
}
所谓的JDBC驱动包,其实就是对服务接口和服务提供者接口的实现
public class NonRegisteringDriver implements java.sql.Driver {
public java.sql.Connection connect(String url, Properties info)
throws SQLException {
...
}
}
//这里的Driver是com.mysql.cj.jdbc.Driver
public class Driver extends NonRegisteringDriver
implements java.sql.Driver {
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
}
上述就是对服务提供者接口的实现。 使用JDBC的第一步就是使用类加载器加载com.mysql.cj.jdbc.Driver的原因,就是调用静态代码块,注册服务提供者接口的实现类
public interface JdbcConnection extends java.sql.Connection...{
...
}
public class ConnectionImpl implements JdbcConnection {
...//实现java.sql.Connection接口
}
上述代码为服务接口的实现类
简单的画一个类图