JDBC驱动加载全过程

最近学习了JDBC,因而决定今天写一篇文章聊聊java是如何进行驱动加载的。java

第一次看到JDBC这个东西的时候,就猜到JDBC应该是Java DataBase Connection的缩写,做用应该就是让java和数据库取得链接,真正开始学的时候,发现正如我猜测的那样JDBC就是Java应用程序和数据库之间的一道桥梁,惟一猜的不对的就是它是Java DataBase Connectivity的缩写,不过无伤大雅。好了,废话很少说,下面咱们直接进入正题。mysql

话说林子大了,什么数据库都有,好比Oracle、MySQL、SQL server等等,每种数据库都有其各自的链接方法,但此时Java就不开心了,它就想:这么多方法我都要干,岂不是要累死,我坚定不能按照大家的规定作,我要作制定标准的那一方,大家这些杂七杂八的数据库必须按照个人规矩来,因而Java就制定了一套链接数据库的标准接口,也就是咱们所说的JDBC。各个数据库厂商实现这些接口,这样Java和数据库的链接就不用那么麻烦了。sql

说了这么多,相信如今你们也应该知道了,一个Java应用程序要想和数据库进行链接,那么就不得不调用JDBC接口,那么第一步要作的就是把数据库厂商的驱动程序加载进系统内存,供系统使用,结构以下图数据库

1.png

上面咱们所说的驱动不过也只是实现了java.sql.driver接口的一个类,如Oracle的驱动类是oracle.jdbc.driver.OracleDriver.class(此类能够在oracle提供的JDBCjar包中找到),此类实现了java.sql.Driver接口。因为驱动的本质是一个类,因此加载驱动的过程其实就是加载类的过程,下面是经常使用的加载数据库驱动的具体代码:oracle

1

加载Oracle数据库驱动框架

Class.forName("oracle.jdbc.driver.OracleDriver");sqlserver

2

加载SQL Server数据库驱动学习

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");测试

3

加载MySQL 数据库驱动url

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


上面咱们能够看到,加载驱动使用的是Class这个类的forName方法(关于Class类,后续有机会再写一篇文章单独介绍),下面是这张图就是Class的forName方法的API


2.png

当咱们在使用Class.forName() 加载oracle的驱动oracle.jdbc.driver.OracleDriver时,会执行OracleDriver中的静态代码段,建立一个OracleDriver实例,而后调用DriverManager.registerDriver()注册,以后就能够利用DriverManager获取链接,从而进行java和数据库之间的对话。下面是我在网上找到的OracleDriver中的静态代码块

7.png

从图中咱们能够发现,当咱们建立一个新的OracleDriver实例时,紧接着就会把该实例向DriverManager进行注册。下面是我经过手动建立OracleDriver实例,验证一下其是否真的会自动向DriverManager进行注册。

3.png

运行结果(看来真的是这么回事):

4.png

关于Driver接口,JDK1.6API这么介绍该接口:每一个驱动程序类必须实现的接口。Java SQL 框架容许多个数据库驱动程序。每一个驱动程序都应该提供一个实现 Driver 接口的类。DriverManager 会试着加载尽量多的它能够找到的驱动程序,而后,对于任何给定链接请求,它会让每一个驱动程序依次试着链接到目标 URL。强烈建议每一个 Driver 类应该是小型的而且是单独的,这样就能够在没必要引入大量支持代码的状况下加载和查询 Driver 类。在加载某一 Driver 类时,它应该建立本身的实例并向 DriverManager 注册该实例。这意味着用户能够经过调用如下程序加载和注册一个驱动程序Class.forName("foo.bah.Driver")。下面是Driver接口定义的方法:

5.png

其中比较重要的两个方法时boolean acceptsURL(String url)Connection connect(String url,Properties info)

 boolean acceptsURL(String url)方法:用来测试对指定的url,该驱动可否打开这个url链接。driver对本身可以链接的url会制定本身的协议,只有符合本身的协议形式的url才认为本身可以打开这个url,若是可以打开,返回true,反之,返回false;

connect(String url,Properties info)方法:建立Connection对象,用来和数据库的数据操做和交互,而Connection则是真正数据库操做的开始(在此方法中,没有规定是否要进行acceptsURL()进行校验),方法中的参数url是要链接到的数据库的URL,info做为链接参数的任意字符串标记/值对的列表。一般至少应该包括user和password属性。

下面是我仅仅利用这两个方法,跳过DriverManager驱动管理,建立和数据库的链接,结果天然也是成功的。

6.png

那么问题来了,既然咱们直接能够经过Driver的实现创建和数据库的链接,为何还要使用DriverManager驱动管理呢?缘由在于上述的链接过程稍显麻烦,并且若是如今咱们加载进来了多个驱动Driver,那么手动建立Driver实例,并根据URL进行建立链接就会显得代码杂乱无章,而且还容易出错,而且不方便管理。因而乎JDBC中为咱们提供了一个DriverManager角色,用来管理这些驱动Driver。

关于DriverManager接口:JDK1.6API中说它管理一组 JDBC 驱动程序的基本服务。下面是它的主要API:

8.png

仔细查看它的API,咱们会发现它的全部方法都为静态方法,也就意味着咱们不用实例化,能够直接进行调用。

DriverManager 内部持有这些注册进来的驱动 Driver,因为这些驱动都是 java.sql.Driver 类型,那么怎样才能得到指定厂商的驱动Driver呢?答案就在于: java.sql.Driver接口规定了厂商实现该接口,而且定义本身的URL协议。厂商们实现的Driver接口经过acceptsURL(String url)来判断此url是否符合本身的协议,若是符合本身的协议,则可使用本驱动进行数据库链接操做,查询驱动程序是否定为它能够打开到给定 URL 的链接。下面详细讲一下它最重要的三个做用:

一、使用DriverManager获取指定的Driver

对于驱动加载后,如何获取指定的驱动程序呢?这里,DriverManager的静态方法getDriver(String url)能够经过传递给的URL,返回能够打开此URL链接的Driver。好比我想得到Oracle的数据库驱动,只须要将Oracle规定的url参数形式传递进去就能够Oracle的数据库驱动

9.png

输出结果:

10.png

实际上,DriverManager.getDriver(String url)方法是根据传递过来的URL,遍历它维护的驱动Driver,依次调用驱动的Driver的acceptsURL(url),若是返回acceptsURL(url)返回true,则返回对应的Driver

二、注册和删除驱动程序

在本文的第一个实例中,咱们验证了驱动的自动注册,如今咱们来验证驱动注册是否为必需要作的事情。首先我利用上述的方法,获取已加载驱动,而后利用DriverManage的static void deregisterDriver(Driver driver)方法删除已加载驱动,而后执行程序,程序会报没法找到指定url的驱动程序

11.png

12.png

上述实验证实了注册驱动为必须的事情,如今我再手动添加建立一个OracleDriver实例并进行注册,而后运行程序。

13.png

14.png

到这里,咱们已经能肯定的说,向DriverManager注册驱动是一件必须的事情,但此时我发现了一个问题,开头不是说建立一个OracleDriver实例就会自动向DriverManager注册驱动吗?怎么这里还必需要手动注册驱动呢?通过个人反复试验得出的结论就是:在一个程序中,只有第一次建立OracleDriver实例时,才会自动进行驱动的注册,也就是说static静态块只会执行一次,因此当咱们将驱动列表的Oracle数据驱动删除以后,列表中将不会再含有Oracle数据驱动,此时若是再建立OracleDriver实例,将不会自动向DriverManager注册驱动,只能经过手动进行驱动注册。

三、使用DriverManager获取链接

经过DriverManager的getConnection(String url,String user, String password)获取与指定数据库的链接,上面的一些事例代码中已经使用的此种方法,因此再也不赘述。