Connection详解

序言

上一节,我们对Connection做了一个简单的介绍,这一把我们对Connection做一个比较详细的解读。

我们可以通过两种方式获取JDBC中的Connection对象:
(1)通过JDBC中提供的DriverManager获取
(2)通过DataSource接口的实现类获取

JDBC驱动类型

JDBC驱动程序有很多可能的实现,这些驱动实现类型主要包括一下几种:

1.JDBC-ODBC Bridge Driver
即桥接模式,其实当初发布JDBC规范的时候,市场上可用的JDBC驱动并不多,已经逐步成熟的ODBC驱动程序几乎可以链接所有类型的数据库,所以有了JDBC-ODBC桥接驱动,利用现成的ODBC架构将JDBC调用转换为ODBC调用。既然是桥接,那么肯定并非所有的功能都能直接转换并正常使用,多层调用转换对性能肯定是有所影响的,如果有第二种方案,不建议用这玩意。

Connection详解_第1张图片

2.Native-api Driver
这类程序直接调用数据库提供的原生数据库或客户端,没有中间过程,速度其实还可以。但是因为与数据库和平台是绑定的,没有办法做到跨平台。所以不推荐。

3.jdbc-net driver
这类驱动会将JDBC调用转为独立于数据库的协议,然后通过特定的中间件或者服务器转换为数据库通信协议,主要目的是获得更好的架构灵活性。更换数据库的时候需要更换中间件。如微软的ADO.NET

Connection详解_第2张图片
4.native protocol Driver
这个是最为常见的JDBC驱动,由数据库厂商直接提供。如:mysql-connector-java,驱动程序吧JDBC调用转为数据库特定的网络通信协议。驱动程序可以通过纯JAVA编写。性能也可以。
Connection详解_第3张图片

java.sql.Driver接口

所有的JDBC驱动都必须实现Driver接口,而且实现类中必须有静态代码块。驱动实现类需要在静态代码快中注册一个自己的实例。当我们

Class.forName("com.mysql.cj.jdbc.Driver")

时候,就会先行加载驱动,为了确保驱动程序调用这种加载机制,Driver实现类需要提供一个无参构造方法。
DriverManager类与注册的驱动程序交互的时候,会调用Driver接口中提供的方法,Driver接口中提供了一个方法

 boolean acceptsURL(String url) throws SQLException;

此时DriverMannager类就可以通过这个方法成功的与数据库建立连接。
当DriverMannager初始化时候

  static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }

 drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
                public String run() {
                    return System.getProperty("jdbc.drivers");
                }
            });

会试图加载jdbc.drivers属性指定的驱动类,因此我们可以通过jdbc.drivers属性来加载驱动:

java -Djdbc.=com.xxx.xxx.xxxDriver Test01

JAVA SPI机制

在JDBC 4.0版本之前,必须要使用代码显示地去加载驱动实现类。之后就不必这么做了。得益于JAVA的SPI机制。
SPI机制是JDK内置的一种服务发现机制。SPI是一种动态替换发现的机制。例如:一个Service接口,只要加了一个实现类,运行的时候就会发现这个类。
Connection详解_第4张图片
当服务的提供者提供了一种接口的实现之后,需要在classpath下的 META-INF/services目录中创建一个以服务接口命名的文件,这个文件中的内容就是接口具体的实现类。当其他的程序需要这个服务的时候,就可以查找这个JAR包META-INF/services目录的配置文件,配置文件中由接口的具体实现类名。可以根据类名加载服务实现类,就可以使用该服务了。
jdk中查找服务实现的工具类是java.util.ServiceLoader,可以玩一下。
写一个Service

public interface SPIService {
	void excute();
}

public class SPIServiceImpl1 implements SPIService {
	@Override
	public void excute() {
		System.out.println("SPIServiceImpl1");
	}
}
public class SPIServiceImpl2 implements SPIService {
	@Override
	public void excute() {
		System.out.println("SPIServiceImpl2");
	}
}

Connection详解_第5张图片

Test类

public class SPITest {
	@Test
	public void testSPI(){
		ServiceLoader<SPIService> spiServices = ServiceLoader.load(SPIService.class);
		for (SPIService spiService : spiServices) {
			spiService.excute();
		}
	}
}

运行结果:

SPIServiceImpl1
SPIServiceImpl2

原本DriverManager类的静态代码块,需要我们手动去Class.forName,现在我们不需要手动的去这么做了。

java.sql.DriverManager接口

DriverManager类通过Driver接口为JDBC接口为JDBC客户端管理一组可用的驱动实现,当客户端通过DriverManager类和数据库建立连接时,DriverManager类会根据getConnection方法参数中的URL找到对应的驱动实现类,然后使用具体的驱动实现连接到对应的数据库。

DriverManager中提供了两个比较关键的静态方法:
registerDriver():该方法用于将驱动实现类注册到DriverManager类中,这个会在驱动加载时隐式地调用,而且通常在每个驱动实现类的静态代码块中调用。
getConnection():这个方法是提供给JDBC客户端调用的,可以接受一个JDBC URL作为参数,DriverManager类会对所有注册驱动进行便利,调用Driver的connect()方法能够识别到JDBC URL的驱动实现后,就会与数据库建立连接,然后返回Connection

`

结束

还有DataSource 因为时间原因下次再说。
码字不易,请点个赞吧

你可能感兴趣的:(Mybatis深入解析源码,数据库,java,服务器)