大家都知道api 但是spi就不那么关注,SPI可以理解是为接口寻找服务实现类。我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。于是就有了SPI这种服务发现机制。
spi最常见的就是数据库连接时候用到 如ojdbc7.jar
Class.forName("oracle.jdbc.driver.OracleDriver");// 加载的底层实现类oracle.jdbc.driver.OracleDriver
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@10.10.1.37:1521:orcl", "root", "123456");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from Users");
加载
加载的类
package oracle.jdbc.driver;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Timestamp;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import oracle.jdbc.OracleDatabaseMetaData;
import oracle.jdbc.babelfish.BabelfishCallableStatement;
import oracle.jdbc.babelfish.BabelfishConnection;
import oracle.jdbc.babelfish.BabelfishGenericProxy;
import oracle.jdbc.babelfish.BabelfishPreparedStatement;
import oracle.jdbc.babelfish.BabelfishStatement;
import oracle.jdbc.babelfish.TranslationManager;
import oracle.jdbc.babelfish.Translator;
import oracle.jdbc.internal.OracleConnection;
import oracle.jdbc.proxy.ProxyFactory;
import oracle.security.pki.OraclePKIProvider;
public class OracleDriver
implements Driver
{
public static final String oracle_string = "oracle";
public static final String jdbc_string = "jdbc";
public static final String protocol_string = "protocol";
public static final String user_string = "user";
public static final String password_string = "password";
public static final String database_string = "database";
public static final String server_string = "server";
/** @deprecated */
public static final String access_string = "access";
/** @deprecated */
public static final String protocolFullName_string = "protocolFullName";
public static final String logon_as_internal_str = "internal_logon";
public static final String proxy_client_name = "oracle.jdbc.proxyClientName";
public static final String prefetch_string = "prefetch";
public static final String row_prefetch_string = "rowPrefetch";
public static final String default_row_prefetch_string = "defaultRowPrefetch";
public static final String batch_string = "batch";
public static final String execute_batch_string = "executeBatch";
public static final String default_execute_batch_string = "defaultExecuteBatch";
public static final String process_escapes_string = "processEscapes";
public static final String accumulate_batch_result = "AccumulateBatchResult";
public static final String j2ee_compliance = "oracle.jdbc.J2EE13Compliant";
public static final String v8compatible_string = "V8Compatible";
public static final String permit_timestamp_date_mismatch_string = "oracle.jdbc.internal.permitBindDateDefineTimestampMismatch";
public static final String prelim_auth_string = "prelim_auth";
public static final String SetFloatAndDoubleUseBinary_string = "SetFloatAndDoubleUseBinary";
/** @deprecated */
public static final String xa_trans_loose = "oracle.jdbc.XATransLoose";
public static final String tcp_no_delay = "oracle.jdbc.TcpNoDelay";
public static final String read_timeout = "oracle.jdbc.ReadTimeout";
public static final String defaultnchar_string = "oracle.jdbc.defaultNChar";
public static final String defaultncharprop_string = "defaultNChar";
public static final String useFetchSizeWithLongColumn_prop_string = "useFetchSizeWithLongColumn";
public static final String useFetchSizeWithLongColumn_string = "oracle.jdbc.useFetchSizeWithLongColumn";
public static final String remarks_string = "remarks";
public static final String report_remarks_string = "remarksReporting";
public static final String synonyms_string = "synonyms";
public static final String include_synonyms_string = "includeSynonyms";
public static final String restrict_getTables_string = "restrictGetTables";
public static final String fixed_string_string = "fixedString";
public static final String dll_string = "oracle.jdbc.ocinativelibrary";
public static final String nls_lang_backdoor = "oracle.jdbc.ociNlsLangBackwardCompatible";
public static final String disable_defineColumnType_string = "disableDefineColumnType";
public static final String convert_nchar_literals_string = "oracle.jdbc.convertNcharLiterals";
public static final String dataSizeUnitsPropertyName = "";
public static final String dataSizeBytes = "";
public static final String dataSizeChars = "";
public static final String set_new_password_string = "OCINewPassword";
public static final String retain_v9_bind_behavior_string = "oracle.jdbc.RetainV9LongBindBehavior";
public static final String no_caching_buffers = "oracle.jdbc.FreeMemoryOnEnterImplicitCache";
static final int EXTENSION_TYPE_ORACLE_ERROR = -3;
static final int EXTENSION_TYPE_GEN_ERROR = -2;
static final int EXTENSION_TYPE_TYPE4_CLIENT = 0;
static final int EXTENSION_TYPE_TYPE4_SERVER = 1;
static final int EXTENSION_TYPE_TYPE2_CLIENT = 2;
static final int EXTENSION_TYPE_TYPE2_SERVER = 3;
private static final int NUMBER_OF_EXTENSION_TYPES = 4;
private OracleDriverExtension[] driverExtensions;
private static final String DRIVER_PACKAGE_STRING = "driver";
private static final String[] driverExtensionClassNames = { "oracle.jdbc.driver.T4CDriverExtension", "oracle.jdbc.driver.T4CDriverExtension", "oracle.jdbc.driver.T2CDriverExtension", "oracle.jdbc.driver.T2SDriverExtension" };
private static Properties driverAccess;
protected static Connection defaultConn = null;
private static OracleDriver defaultDriver = null;
public static final Map<String, Class> systemTypeMap;
private static final String DEFAULT_CONNECTION_PROPERTIES_RESOURCE_NAME = "/oracle/jdbc/defaultConnectionProperties.properties";
protected static final Properties DEFAULT_CONNECTION_PROPERTIES;
private static ObjectName diagnosticMBeanObjectName;
private static final String _Copyright_2007_Oracle_All_Rights_Reserved_;
public static final String BUILD_DATE = "Thu_Apr_04_15:09:24_PDT_2013";
public static final boolean TRACE = 0;
public OracleDriver()
{
this.driverExtensions = new OracleDriverExtension[4];
}
public static void registerMBeans()
{
try
{
MBeanServer localMBeanServer = null;
Object localObject;
try {
Class localClass = Class.forName("oracle.as.jmx.framework.PortableMBeanFactory");
localObject = localClass.newInstance();
Method localMethod = localClass.getMethod("getMBeanServer", new Class[0]);
localMBeanServer = (MBeanServer)localMethod.invoke(localObject, new Object[0]);
}
catch (NoClassDefFoundError localNoClassDefFoundError)
{
localMBeanServer = ManagementFactory.getPlatformMBeanServer();
}
catch (ClassNotFoundException localClassNotFoundException)
{
localMBeanServer = ManagementFactory.getPlatformMBeanServer();
}
catch (NoSuchMethodException localNoSuchMethodException) {
Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Found Oracle Apps MBeanServer but not the getMBeanServer method.", localNoSuchMethodException);
localMBeanServer = ManagementFactory.getPlatformMBeanServer();
}
catch (InstantiationException localInstantiationException) {
Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Found Oracle Apps MBeanServer but could not create an instance.", localInstantiationException);
localMBeanServer = ManagementFactory.getPlatformMBeanServer();
}
catch (IllegalAccessException localIllegalAccessException) {
Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Found Oracle Apps MBeanServer but could not access the getMBeanServer method.", localIllegalAccessException);
localMBeanServer = ManagementFactory.getPlatformMBeanServer();
}
catch (InvocationTargetException localInvocationTargetException) {
Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Found Oracle Apps MBeanServer but the getMBeanServer method threw an exception.", localInvocationTargetException);
localMBeanServer = ManagementFactory.getPlatformMBeanServer();
}
if (localMBeanServer != null) {
ClassLoader localClassLoader = OracleDriver.class.getClassLoader();
localObject = (localClassLoader == null) ? "nullLoader" : localClassLoader.getClass().getName();
int i = 0;
while (true) {
String str = new StringBuilder().append((String)localObject).append("@").append(Integer.toHexString(((localClassLoader == null) ? 0 : localClassLoader.hashCode()) + i++)).toString();
diagnosticMBeanObjectName = new ObjectName(new StringBuilder().append("com.oracle.jdbc:type=diagnosability,name=").append(str).toString());
try
{
localMBeanServer.registerMBean(new OracleDiagnosabilityMBean(), diagnosticMBeanObjectName);
}
catch (InstanceAlreadyExistsException localInstanceAlreadyExistsException)
{
}
}
}
else {
Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Unable to find an MBeanServer so no MBears are registered.");
}
}
catch (JMException localJMException)
{
Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Error while registering Oracle JDBC Diagnosability MBean.", localJMException);
}
catch (Throwable localThrowable)
{
Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Error while registering Oracle JDBC Diagnosability MBean.", localThrowable);
}
}
public Connection connect(String paramString, Properties paramProperties)
throws SQLException
{
if (paramString.regionMatches(0, "jdbc:default:connection", 0, 23))
{
String str1 = "jdbc:oracle:kprb";
int j = paramString.length();
if (j > 23)
paramString = str1.concat(paramString.substring(23, paramString.length()));
else {
paramString = str1.concat(":");
}
str1 = null;
}
int i = oracleDriverExtensionTypeFromURL(paramString);
if (i == -2) {
return null;
}
if (i == -3)
{
localObject1 = DatabaseError.createSqlException(getConnectionDuringExceptionHandling(), 67);
((SQLException)localObject1).fillInStackTrace();
throw ((Throwable)localObject1);
}
Object localObject1 = null;
localObject1 = this.driverExtensions[i];
if (localObject1 == null)
{
try
{
synchronized (this)
{
if (localObject1 == null)
{
localObject1 = (OracleDriverExtension)Class.forName(driverExtensionClassNames[i]).newInstance();
this.driverExtensions[i] = localObject1;
}
else
{
localObject1 = this.driverExtensions[i];
}
}
}
catch (Exception localException)
{
localObject3 = DatabaseError.createSqlException(getConnectionDuringExceptionHandling(), localException);
((SQLException)localObject3).fillInStackTrace();
throw ((Throwable)localObject3);
}
}
if (paramProperties == null) {
paramProperties = new Properties();
}
Enumeration localEnumeration = DriverManager.getDrivers();
while (localEnumeration.hasMoreElements())
{
localObject3 = (Driver)(Driver)localEnumeration.nextElement();
if (localObject3 instanceof OracleDriver) {
break;
}
}
while (localEnumeration.hasMoreElements())
{
localObject3 = (Driver)(Driver)localEnumeration.nextElement();
if (localObject3 instanceof OracleDriver) {
DriverManager.deregisterDriver((Driver)localObject3);
}
}
Object localObject3 = null;
if ((i != 2) || (!(paramProperties.containsKey("connection_pool"))) || (!(paramProperties.getProperty("connection_pool").equals("connection_pool"))))
{
String str2 = null;
if (paramProperties != null)
{
str2 = paramProperties.getProperty("oracle.jdbc.sqlTranslationProfile");
}
if (str2 == null)
{
str2 = PhysicalConnection.getSqlTranslationProfile();
}
if (str2 != null)
{
localObject3 = babelfishConnect(paramProperties, str2, paramString, (OracleDriverExtension)localObject1, i);
}
else
{
localObject3 = (PhysicalConnection)((OracleDriverExtension)localObject1).getConnection(paramString, paramProperties);
((PhysicalConnection)localObject3).protocolId = i;
}
}
else
{
localObject3 = (PhysicalConnection)((OracleDriverExtension)localObject1).getConnection(paramString, paramProperties);
((PhysicalConnection)localObject3).protocolId = i;
}
return ((Connection)(Connection)localObject3);
}
private Connection babelfishConnect(Properties paramProperties, String paramString1, String paramString2, OracleDriverExtension paramOracleDriverExtension, int paramInt)
throws SQLException
{
paramProperties.put("oracle.jdbc.sqlTranslationProfile", paramString1);
paramString1 = null;
if (paramProperties != null)
{
paramString1 = paramProperties.getProperty("oracle.jdbc.sqlErrorTranslationFile");
}
if (paramString1 == null)
{
paramString1 = System.getProperty("oracle.jdbc.sqlErrorTranslationFile", null);
}
if (paramString1 != null)
{
paramProperties.put("oracle.jdbc.sqlErrorTranslationFile", paramString1);
}
paramString1 = null;
if (paramProperties != null)
{
paramString1 = paramProperties.getProperty("user");
if (paramString1 == null)
{
paramString1 = paramProperties.getProperty("oracle.jdbc.user");
}
}
if (paramString1 == null)
{
paramString1 = System.getProperty("oracle.jdbc.user", null);
}
if (paramString1 == null)
{
localObject = PhysicalConnection.parseUrl(paramString2, null, null);
paramString1 = (String)((Hashtable)localObject).get("user");
}
paramProperties.put("user", paramString1);
Object localObject = ProxyFactory.createJDBCProxyFactory(new Class[] { BabelfishGenericProxy.class, BabelfishConnection.class, BabelfishStatement.class, BabelfishPreparedStatement.class, BabelfishCallableStatement.class });
Translator localTranslator = TranslationManager.getTranslator(paramString2, paramProperties.getProperty("user"), paramProperties.getProperty("oracle.jdbc.sqlTranslationProfile"), paramProperties.getProperty("oracle.jdbc.sqlErrorTranslationFile"));
try
{
PhysicalConnection localPhysicalConnection = (PhysicalConnection)paramOracleDriverExtension.getConnection(paramString2, paramProperties);
localPhysicalConnection.protocolId = paramInt;
Connection localConnection = (Connection)((ProxyFactory)localObject).proxyFor(localPhysicalConnection);
((BabelfishConnection)localConnection).setTranslator(localTranslator);
localTranslator.activateServerTranslation(localPhysicalConnection);
return localConnection;
}
catch (SQLException localSQLException)
{
throw localTranslator.translateError(localSQLException);
}
}
public Connection defaultConnection()
throws SQLException
{
if ((defaultConn == null) || (defaultConn.isClosed()))
{
synchronized (OracleDriver.class)
{
if ((defaultConn == null) || (defaultConn.isClosed()))
{
defaultConn = connect("jdbc:oracle:kprb:", new Properties());
}
}
}
return defaultConn;
}
static final int oracleDriverExtensionTypeFromURL(String paramString)
{
int i = paramString.indexOf(58);
if (i == -1) {
return -2;
}
if (!(paramString.regionMatches(true, 0, "jdbc", 0, i))) {
return -2;
}
++i;
int j = paramString.indexOf(58, i);
if (j == -1) {
return -2;
}
if (!(paramString.regionMatches(true, i, "oracle", 0, j - i)))
{
return -2;
}
++j;
int k = paramString.indexOf(58, j);
String str = null;
if (k == -1) {
return -3;
}
str = paramString.substring(j, k);
if (str.equals("thin")) {
return 0;
}
if ((str.equals("oci8")) || (str.equals("oci"))) {
return 2;
}
return -3;
}
public boolean acceptsURL(String paramString)
{
if (paramString.startsWith("jdbc:oracle:"))
{
return (oracleDriverExtensionTypeFromURL(paramString) > -2);
}
return false;
}
public DriverPropertyInfo[] getPropertyInfo(String paramString, Properties paramProperties)
throws SQLException
{
Class localClass = null;
try
{
localClass = Class.forName("oracle.jdbc.OracleConnection");
}
catch (ClassNotFoundException localClassNotFoundException) {
}
int i = 0;
Object localObject1 = new String[150];
Object localObject2 = new String[150];
Field[] arrayOfField = localClass.getFields();
for (int j = 0; j < arrayOfField.length; ++j)
{
if ((!(arrayOfField[j].getName().startsWith("CONNECTION_PROPERTY_"))) || (arrayOfField[j].getName().endsWith("_DEFAULT")) || (arrayOfField[j].getName().endsWith("_ACCESSMODE"))) {
continue;
}
try
{
String str1 = (String)arrayOfField[j].get(null);
Field localField = localClass.getField(new StringBuilder().append(arrayOfField[j].getName()).append("_DEFAULT").toString());
String str2 = (String)localField.get(null);
if (i == localObject1.length)
{
String[] arrayOfString1 = new String[localObject1.length * 2];
String[] arrayOfString2 = new String[localObject1.length * 2];
System.arraycopy(localObject1, 0, arrayOfString1, 0, localObject1.length);
System.arraycopy(localObject2, 0, arrayOfString2, 0, localObject1.length);
localObject1 = arrayOfString1;
localObject2 = arrayOfString2;
}
localObject1[i] = str1;
localObject2[i] = str2;
++i;
}
catch (IllegalAccessException localIllegalAccessException)
{
}
catch (NoSuchFieldException localNoSuchFieldException) {
}
}
DriverPropertyInfo[] arrayOfDriverPropertyInfo = new DriverPropertyInfo[i];
for (int k = 0; k < i; ++k)
arrayOfDriverPropertyInfo[k] = new DriverPropertyInfo(localObject1[k], localObject2[k]);
return ((DriverPropertyInfo)(DriverPropertyInfo)arrayOfDriverPropertyInfo);
}
public int getMajorVersion()
{
return OracleDatabaseMetaData.getDriverMajorVersionInfo();
}
public int getMinorVersion()
{
return OracleDatabaseMetaData.getDriverMinorVersionInfo();
}
public boolean jdbcCompliant()
{
return true;
}
public String processSqlEscapes(String paramString)
throws SQLException
{
OracleSql localOracleSql = new OracleSql(null);
localOracleSql.initialize(paramString);
return localOracleSql.parse(paramString);
}
public static String getCompileTime()
{
return "Thu_Apr_04_15:09:24_PDT_2013";
}
public static String getSystemPropertyFastConnectionFailover(String paramString)
{
return PhysicalConnection.getSystemPropertyFastConnectionFailover(paramString);
}
protected OracleConnection getConnectionDuringExceptionHandling()
{
return null;
}
public Logger getParentLogger()
throws SQLFeatureNotSupportedException
{
return Logger.getLogger("oracle");
}
protected void finalize()
throws Throwable
{
if (diagnosticMBeanObjectName == null)
return;
try
{
MBeanServer localMBeanServer = null;
try
{
Class localClass = Class.forName("oracle.as.jmx.framework.PortableMBeanFactory");
Object localObject = localClass.newInstance();
Method localMethod = localClass.getMethod("getMBeanServer", new Class[0]);
localMBeanServer = (MBeanServer)localMethod.invoke(localObject, new Object[0]);
}
catch (Throwable localThrowable2)
{
localMBeanServer = ManagementFactory.getPlatformMBeanServer();
}
if (localMBeanServer != null)
{
try
{
localMBeanServer.unregisterMBean(diagnosticMBeanObjectName);
}
catch (InstanceNotFoundException localInstanceNotFoundException) {
}
}
else Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Unable to find an MBeanServer so no MBeans are unregistered.");
}
catch (Throwable localThrowable1)
{
Logger.getLogger("oracle.jdbc").log(Level.WARNING, "Error while unregistering Oracle JDBC Diagnosability MBean.", localThrowable1);
}
}
static
{
try
{
if (defaultDriver == null)
{
defaultDriver = new oracle.jdbc.OracleDriver();
DriverManager.registerDriver(defaultDriver);
}
AccessController.doPrivileged(new PrivilegedAction()
{
public Object run()
{
OracleDriver.registerMBeans();
return null;
}
});
Timestamp localTimestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");
}
catch (SQLException localSQLException)
{
Logger.getLogger("oracle.jdbc.driver").log(Level.SEVERE, "SQLException in static block.", localSQLException);
}
catch (RuntimeException localRuntimeException)
{
Logger.getLogger("oracle.jdbc.driver").log(Level.SEVERE, "RuntimeException in static block.", localRuntimeException);
}
try
{
OraclePKIProvider localOraclePKIProvider = new OraclePKIProvider();
}
catch (Throwable localThrowable)
{
}
systemTypeMap = new Hashtable(2);
try
{
systemTypeMap.put("SYS.ANYDATA", Class.forName("oracle.sql.AnyDataFactory"));
systemTypeMap.put("SYS.ANYTYPE", Class.forName("oracle.sql.TypeDescriptorFactory"));
}
catch (ClassNotFoundException localClassNotFoundException)
{
}
DEFAULT_CONNECTION_PROPERTIES = new Properties();
try
{
InputStream localInputStream = PhysicalConnection.class.getResourceAsStream("/oracle/jdbc/defaultConnectionProperties.properties");
if (localInputStream != null) DEFAULT_CONNECTION_PROPERTIES.load(localInputStream);
}
catch (IOException localIOException)
{
}
diagnosticMBeanObjectName = null;
_Copyright_2007_Oracle_All_Rights_Reserved_ = null;
}
}
以上类
OracleDriver
是实现了Driver接口
package java.sql;
import java.util.logging.Logger;
public interface Driver {
Connection connect(String url, java.util.Properties info)
throws SQLException;
boolean acceptsURL(String url) throws SQLException;
DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info)
throws SQLException;
int getMajorVersion();
int getMinorVersion();
boolean jdbcCompliant();
public Logger getParentLogger() throws SQLFeatureNotSupportedException;
}
这个类是一个接口类, 在整个JDK包中都没有它的实现类,它的实现要由各个jdbc的开发产商去实现,但是我们发现DriverManager这个类中还是有去加载Driver类,那它是怎么发现其它开发商实现的Driver类?
在 ojdbc7\META-INF\services 下有一个文件名为java.sql.Driver的文件 其内容是oracle.jdbc.OracleDriver
package oracle.jdbc;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Properties;
public class OracleDriver extends oracle.jdbc.driver.OracleDriver //这个是关键,最终指向这个类
{
private static final String _Copyright_2007_Oracle_All_Rights_Reserved_ = null;
public static final String BUILD_DATE = "Thu_Apr_04_15:09:24_PDT_2013";
public static final boolean TRACE = 0;
public static final boolean isDMS()
{
return false;
}
public static final boolean isInServer()
{
return false;
}
/** @deprecated */
public static final boolean isJDK14()
{
return true;
}
public static final boolean isDebug()
{
return false;
}
public static final boolean isPrivateDebug()
{
return false;
}
public static final String getJDBCVersion()
{
return "JDBC 4.1";
}
public static final String getDriverVersion()
{
return "12.1.0.1.0";
}
public static final String getBuildDate()
{
return "Thu_Apr_04_15:09:24_PDT_2013";
}
public static void main(String[] paramArrayOfString)
throws Exception
{
String str = "JDK7";
System.out.println(new StringBuilder().append("Oracle ").append(getDriverVersion()).append(" ").append(getJDBCVersion()).append((isDMS()) ? " DMS" : "").append((isPrivateDebug()) ? " private" : "").append((isDebug()) ? " debug" : "").append((isInServer()) ? " for JAVAVM" : "").append(" compiled with ").append(str).append(" on ").append(getBuildDate()).toString());
ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream(128);
DEFAULT_CONNECTION_PROPERTIES.store(localByteArrayOutputStream, "Default Connection Properties Resource");
System.out.println(localByteArrayOutputStream.toString("ISO-8859-1"));
}
}
在service下的文件名“ava.sql.Driver”是介绍了其实现的接口是哪个,其内容是oracle.jdbc.OracleDriver是其实现类
注意:这些spi都是手动配置的,如果自己要写spi就需要手动去配置,META-INF\services 下的接口名 java.sql.Driver 其中内容是这个接口的实现类,