SlideShare a Scribd company logo
JDBC 中驱动加载的过程分析(下)

                                                                                       江苏 无锡 缪小东
  本篇主要用几个开源数据库的驱动讲述驱动是如何加载的,以及“可插拔”机制等。
  由于文章篇幅有限,本文章并不是专门研究开源源代码!因此我们仅研究那些与数据库驱动加载直
接相关的方法。在下面的几个开源软件的驱动中,我们主要关注驱动类的 getConnection()方法。


一、几个开源数据库的驱动类

   以下第一个是 smallsql 中驱动类 SSDriver 的源代码:
   package smallsql.database;
   import java.sql.*;
   import java.util.Properties;
   public class SSDriver implements Driver {
         static SSDriver drv;
         static {
               try{
                     drv = new SSDriver();
                     java.sql.DriverManager.registerDriver(drv);
               }catch(Throwable e){}
         }

        public Connection connect(String url, Properties info) throws SQLException {
              if(!acceptsURL(url)) return null;
              ……
              return new SSConnection( (idx > 0) ? url.substring(idx+1) : null);
        }
        ……
  }
  从上面红色的部分可以看到:这是一个静态语句块(static block)        ,这意味着该语句是在类构造完成
前完成的(关于语句块的加载请阅读《Think in java》。即调用 class.forName(“smallsql.database.SSDriver”)语句
                                   )
时,会首先创建一个 SSDriver 的实例,并且将其向驱动管理器(DriverManager)注册。这样就完成驱动的注
册了。
  从上面的蓝色的代码可以看出:驱动的连接方法返回的是一个具体的 SSConnection 对象。而在前面
研究的 Driver 接口中返回的是 Connection 接口,这是不茅盾的,SSConnection 对象实现了 Connection 接口。

   再下面一个是 HSqlD 中的驱动类的源代码:
   package org.hsqldb;
   import java.sql.*;
   import java.util.Properties;
   import org.hsqldb.jdbc.jdbcConnection;
   import org.hsqldb.persist.HsqlDatabaseProperties;
   import org.hsqldb.persist.HsqlProperties;
   public class jdbcDriver implements Driver {

                                                          1
public Connection connect(String url, Properties info) throws SQLException {
              return getConnection(url, info);
        }

        public static Connection getConnection(String url, Properties info) throws SQLException {
              HsqlProperties props = DatabaseURL.parseURL(url, true);
              if (props == null) {
                     throw new SQLException(Trace.getMessage(Trace.INVALID_JDBC_ARGUMENT));
              } else if (props.isEmpty()) {
                     return null;
              }
              props.addProperties(info);
              return new jdbcConnection(props);
        }

        static {
              try {
                    DriverManager.registerDriver(new jdbcDriver());
              } catch (Exception e) {}
        }
   }

   蓝色的依然是建立连接的部分,依然返回某个具体的实现 java.sql.Connection 接口的对象。是设计
模式中的哪个工厂啊(一般工厂、抽象工厂、工厂方法还是什么都不是啊)                                    !
   红色的同样是一个静态语句块,同样完成该驱动的注册。
   两个开源数据库的驱动竟然如此相似,是不是其它的就不一样呢!看下面是 mckoi 中的驱动类:
   package com.mckoi;
   public class JDBCDriver extends com.mckoi.database.jdbc.MDriver {
      static {
         com.mckoi.database.jdbc.MDriver.register();
      }
      public JDBCDriver() {
         super();
         // Or we could move driver registering here...
      }
   }
   红色的部分又是完成相同的工作――在类装载完成前向驱动管理器注册驱动,只不过这次是调用
MDriver 的 register 方法罢了。那么该驱动建立连接是否也一样呢,当然一样啦!不信你看下面的代码:

   package com.mckoi.database.jdbc;
   ……
   public class MDriver implements Driver {
         ……
     private static boolean registered = false;
     public synchronized static void register() {
         if (registered == false) {
             try {
                                                          2
java.sql.DriverManager.registerDriver(new MDriver());
                    registered = true;
                 }catch (SQLException e) {
                    e.printStackTrace();
                 }
             }
         }

         public Connection connect(String url, Properties info) throws SQLException {
           if (!acceptsURL(url)) {       return null;      }
           DatabaseInterface db_interface;
           int row_cache_size;
           int max_row_cache_size;
           ……
           MConnection connection = new MConnection(url, db_interface, row_cache_size, max_row_cache_size);
           ……
           return connection;
         }
     }

  从以上三个开源数据库驱动的源代码可以看出:                 在调用 Class.forName(“XXXDriver”)时,完成了将具体
的驱动程序向 JDBC API 中驱动管理器的注册,            该注册方法在类构造完成前完成,            一般使用静态语句块。
在调用 DriverManager 的 getConnection 方法时,一般先在已注册的驱动中查找可以了解此 URL 的驱动,
然后调用该驱动的 connect 方法,从而建立连接,返回的连接都是一个实现 java.sql.Connection 接口的具
体类。下面是该过程的时序图。


二、JDBC 中驱动加载的时序图




     以上是 JDBC 中驱动加载的时序图。时序图主要有以下 7 个动作:
1.   客户调用 Class.forName(“XXXDriver”)加载驱动。
2.   此时此驱动类首先在其静态语句块中初始化此驱动的实例,
3.   再向驱动管理器注册此驱动。
                                                                3
4.   客户向驱动管理器 DriverManager 调用 getConnection 方法,
5.   DriverManager 调用注册到它上面的能够理解此 URL 的驱动建立一个连接,
6.   在该驱动中建立一个连接,一般会创建一个对应于数据库提供商的 XXXConnection 连接对象,
7.   驱 动 向 客 户 返 回 此 连 接 对 象 , 不 过 在 客 户 调 用 的 getConnection 方 法 中 返 回 的 为 一 个
     java.sql.Connection 接口,而具体的驱动返回一个实现 java.sql.Connection 接口的具体类。
     以上就是驱动加载的全过程。由此过程我们可以看出 JDBC 的其它一些特点。


三、JDBC 的架构

  在《教你建立简单 JDBC 程序》一篇中,讲述了一般 JDBC 的几个步骤。通过本篇的介绍,我将此
程序分为以下几部分:




     上图中,蓝色的即为本章前面介绍的 JDBC 驱动加载的细节部分。看看下面的部分:左面的很明显
吧!是 java.sql 包中的接口吧!它是抽象的!右边呢?通过驱动管理器 DriverManager 得到的是一个实现
java.sql.Connection 接口的具体类吧!
                           (不知道啊!前面不是讲过了吗!)因此我们可以可以注意到左右分
别是抽象的和具体的。 这种抽象和具体的连接是由 java 的 RTTI 支持的,
                     (                      不懂可以阅读    《Think in java》。
                                                                     )
在接下来的结果集的处理 rs 也是抽象的吧!
     因此,在写 JDBC 程序时,即使我们使用不同数据库提供商的数据库我们只要改变驱动类的地址,
和具体连接的 URL 及其用户名和密码,其它几乎不用任何修改,就可以完成同样的工作!方便吧!
     这意味着什么呢?我们其实是在针对抽象接口编程,只要知道接口的调用顺序,以及其中的主要方
法,我们就可以迅速学会 JDBC 编程了!
     同时,我们只要对不同数据库提供商的驱动类使用 Class.forName(“XXXDriver”)就可以加载驱动,
其细节你根本不用关注――JDBC Framework 已经全为你搞定了!应用程序对于不同提供商的数据库是
无需太多改动的,因而其是“可插拔”的!整个 J2EE 就是一个高层的 API――抽象接口,用户可以使
                                       4
用不同的产品提供商提供的产品,使用统一的 API,从而便于程序员学习!
  谢谢大家!到此结束!


更多精彩请关注:
  http://blog.163.com/miaoxiaodong78/




                       5

More Related Content

What's hot

Hibernate的高级操作
Hibernate的高级操作Hibernate的高级操作
Hibernate的高级操作yiditushe
 
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocketpwesh
 
千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7
javatwo2011
 
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 -  回歸到最純樸的開發山頂洞人日記 -  回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發
koji lin
 
Oracle面市笔记
Oracle面市笔记Oracle面市笔记
Oracle面市笔记yiditushe
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非Tony Deng
 
Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期yiditushe
 
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 SpringSpring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Justin Lin
 
Mes 實作 第四週
Mes 實作 第四週Mes 實作 第四週
Mes 實作 第四週
信宏 陳
 
百度分布式数据实践与进展
百度分布式数据实践与进展百度分布式数据实践与进展
百度分布式数据实践与进展yp_fangdong
 
基于J2 Ee 的通用Web 信息系统框架设计与实现
基于J2 Ee 的通用Web 信息系统框架设计与实现基于J2 Ee 的通用Web 信息系统框架设计与实现
基于J2 Ee 的通用Web 信息系统框架设计与实现yiditushe
 

What's hot (12)

Structs2簡介
Structs2簡介 Structs2簡介
Structs2簡介
 
Hibernate的高级操作
Hibernate的高级操作Hibernate的高级操作
Hibernate的高级操作
 
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocket
 
千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7
 
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 -  回歸到最純樸的開發山頂洞人日記 -  回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發
 
Oracle面市笔记
Oracle面市笔记Oracle面市笔记
Oracle面市笔记
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非
 
Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期
 
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 SpringSpring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
 
Mes 實作 第四週
Mes 實作 第四週Mes 實作 第四週
Mes 實作 第四週
 
百度分布式数据实践与进展
百度分布式数据实践与进展百度分布式数据实践与进展
百度分布式数据实践与进展
 
基于J2 Ee 的通用Web 信息系统框架设计与实现
基于J2 Ee 的通用Web 信息系统框架设计与实现基于J2 Ee 的通用Web 信息系统框架设计与实现
基于J2 Ee 的通用Web 信息系统框架设计与实现
 

Viewers also liked

Jdbc Odbc使用Excel作数据源
Jdbc Odbc使用Excel作数据源Jdbc Odbc使用Excel作数据源
Jdbc Odbc使用Excel作数据源yiditushe
 
Java相关基础知识
Java相关基础知识Java相关基础知识
Java相关基础知识yiditushe
 
Java 推荐读物
Java 推荐读物Java 推荐读物
Java 推荐读物yiditushe
 
Java案例开发集锦
Java案例开发集锦Java案例开发集锦
Java案例开发集锦yiditushe
 
Java 面试32问
Java 面试32问Java 面试32问
Java 面试32问yiditushe
 
1 软件开发过程概述
1  软件开发过程概述1  软件开发过程概述
1 软件开发过程概述yiditushe
 
Java华为面试题
Java华为面试题Java华为面试题
Java华为面试题yiditushe
 
Prototype开发手册
Prototype开发手册Prototype开发手册
Prototype开发手册yiditushe
 
Linux必学的60个命令
Linux必学的60个命令Linux必学的60个命令
Linux必学的60个命令yiditushe
 

Viewers also liked (9)

Jdbc Odbc使用Excel作数据源
Jdbc Odbc使用Excel作数据源Jdbc Odbc使用Excel作数据源
Jdbc Odbc使用Excel作数据源
 
Java相关基础知识
Java相关基础知识Java相关基础知识
Java相关基础知识
 
Java 推荐读物
Java 推荐读物Java 推荐读物
Java 推荐读物
 
Java案例开发集锦
Java案例开发集锦Java案例开发集锦
Java案例开发集锦
 
Java 面试32问
Java 面试32问Java 面试32问
Java 面试32问
 
1 软件开发过程概述
1  软件开发过程概述1  软件开发过程概述
1 软件开发过程概述
 
Java华为面试题
Java华为面试题Java华为面试题
Java华为面试题
 
Prototype开发手册
Prototype开发手册Prototype开发手册
Prototype开发手册
 
Linux必学的60个命令
Linux必学的60个命令Linux必学的60个命令
Linux必学的60个命令
 

Similar to Jdbc中驱动加载的过程分析(下)

常用数据库的链接方法
常用数据库的链接方法常用数据库的链接方法
常用数据库的链接方法wensheng wei
 
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit TestingASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
江華 奚
 
JdonFramework中文
JdonFramework中文JdonFramework中文
JdonFramework中文
banq jdon
 
J2ee经典学习笔记
J2ee经典学习笔记J2ee经典学习笔记
J2ee经典学习笔记yiditushe
 
Spring 2.0 技術手冊第五章 - JDBC、交易支援
Spring 2.0 技術手冊第五章 - JDBC、交易支援Spring 2.0 技術手冊第五章 - JDBC、交易支援
Spring 2.0 技術手冊第五章 - JDBC、交易支援
Justin Lin
 
前端MVC之backbone
前端MVC之backbone前端MVC之backbone
前端MVC之backbone
Jerry Xie
 
Cassandra的初步使用及一些简单的操作
Cassandra的初步使用及一些简单的操作Cassandra的初步使用及一些简单的操作
Cassandra的初步使用及一些简单的操作
zhubin885
 
用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services
javatwo2011
 
Underscore
UnderscoreUnderscore
Underscore
cazhfe
 
Oracle sql developer支持第三方数据库
Oracle  sql developer支持第三方数据库Oracle  sql developer支持第三方数据库
Oracle sql developer支持第三方数据库
shadowfalao
 
Thinking in React by Deot
Thinking in React by Deot Thinking in React by Deot
Thinking in React by Deot
荣德 周
 
ASP.NET Core 2.1設計新思維與新發展
ASP.NET  Core 2.1設計新思維與新發展ASP.NET  Core 2.1設計新思維與新發展
ASP.NET Core 2.1設計新思維與新發展
江華 奚
 
Essential oracle security internal for dba
Essential oracle security internal for dbaEssential oracle security internal for dba
Essential oracle security internal for dbamaclean liu
 
在Windows azure平台上進行資料庫處理及架構設計
在Windows azure平台上進行資料庫處理及架構設計在Windows azure平台上進行資料庫處理及架構設計
在Windows azure平台上進行資料庫處理及架構設計
Sky Chang
 
Ria的强力后盾:rest+海量存储
Ria的强力后盾:rest+海量存储 Ria的强力后盾:rest+海量存储
Ria的强力后盾:rest+海量存储
zhen chen
 
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Justin Lin
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Wade Huang
 
Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫
Justin Lin
 

Similar to Jdbc中驱动加载的过程分析(下) (20)

常用数据库的链接方法
常用数据库的链接方法常用数据库的链接方法
常用数据库的链接方法
 
Jdbc
JdbcJdbc
Jdbc
 
Jsp
JspJsp
Jsp
 
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit TestingASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
 
JdonFramework中文
JdonFramework中文JdonFramework中文
JdonFramework中文
 
J2ee经典学习笔记
J2ee经典学习笔记J2ee经典学习笔记
J2ee经典学习笔记
 
Spring 2.0 技術手冊第五章 - JDBC、交易支援
Spring 2.0 技術手冊第五章 - JDBC、交易支援Spring 2.0 技術手冊第五章 - JDBC、交易支援
Spring 2.0 技術手冊第五章 - JDBC、交易支援
 
前端MVC之backbone
前端MVC之backbone前端MVC之backbone
前端MVC之backbone
 
Cassandra的初步使用及一些简单的操作
Cassandra的初步使用及一些简单的操作Cassandra的初步使用及一些简单的操作
Cassandra的初步使用及一些简单的操作
 
用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services
 
Underscore
UnderscoreUnderscore
Underscore
 
Oracle sql developer支持第三方数据库
Oracle  sql developer支持第三方数据库Oracle  sql developer支持第三方数据库
Oracle sql developer支持第三方数据库
 
Thinking in React by Deot
Thinking in React by Deot Thinking in React by Deot
Thinking in React by Deot
 
ASP.NET Core 2.1設計新思維與新發展
ASP.NET  Core 2.1設計新思維與新發展ASP.NET  Core 2.1設計新思維與新發展
ASP.NET Core 2.1設計新思維與新發展
 
Essential oracle security internal for dba
Essential oracle security internal for dbaEssential oracle security internal for dba
Essential oracle security internal for dba
 
在Windows azure平台上進行資料庫處理及架構設計
在Windows azure平台上進行資料庫處理及架構設計在Windows azure平台上進行資料庫處理及架構設計
在Windows azure平台上進行資料庫處理及架構設計
 
Ria的强力后盾:rest+海量存储
Ria的强力后盾:rest+海量存储 Ria的强力后盾:rest+海量存储
Ria的强力后盾:rest+海量存储
 
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有
 
Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫
 

More from yiditushe

Spring入门纲要
Spring入门纲要Spring入门纲要
Spring入门纲要yiditushe
 
J Bpm4 1中文用户手册
J Bpm4 1中文用户手册J Bpm4 1中文用户手册
J Bpm4 1中文用户手册yiditushe
 
性能测试实践2
性能测试实践2性能测试实践2
性能测试实践2yiditushe
 
性能测试实践1
性能测试实践1性能测试实践1
性能测试实践1yiditushe
 
性能测试技术
性能测试技术性能测试技术
性能测试技术yiditushe
 
Load runner测试技术
Load runner测试技术Load runner测试技术
Load runner测试技术yiditushe
 
J2 ee性能测试
J2 ee性能测试J2 ee性能测试
J2 ee性能测试yiditushe
 
面向对象的Js培训
面向对象的Js培训面向对象的Js培训
面向对象的Js培训yiditushe
 
Flex3中文教程
Flex3中文教程Flex3中文教程
Flex3中文教程yiditushe
 
开放源代码的全文检索Lucene
开放源代码的全文检索Lucene开放源代码的全文检索Lucene
开放源代码的全文检索Luceneyiditushe
 
基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍yiditushe
 
Lucene In Action
Lucene In ActionLucene In Action
Lucene In Actionyiditushe
 
Lucene2 4学习笔记1
Lucene2 4学习笔记1Lucene2 4学习笔记1
Lucene2 4学习笔记1yiditushe
 
Lucene2 4 Demo
Lucene2 4 DemoLucene2 4 Demo
Lucene2 4 Demoyiditushe
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践yiditushe
 
Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析yiditushe
 
7 面向对象设计原则
7 面向对象设计原则7 面向对象设计原则
7 面向对象设计原则yiditushe
 
10 团队开发
10  团队开发10  团队开发
10 团队开发yiditushe
 
9 对象持久化与数据建模
9  对象持久化与数据建模9  对象持久化与数据建模
9 对象持久化与数据建模yiditushe
 
8 Uml构架建模
8  Uml构架建模8  Uml构架建模
8 Uml构架建模yiditushe
 

More from yiditushe (20)

Spring入门纲要
Spring入门纲要Spring入门纲要
Spring入门纲要
 
J Bpm4 1中文用户手册
J Bpm4 1中文用户手册J Bpm4 1中文用户手册
J Bpm4 1中文用户手册
 
性能测试实践2
性能测试实践2性能测试实践2
性能测试实践2
 
性能测试实践1
性能测试实践1性能测试实践1
性能测试实践1
 
性能测试技术
性能测试技术性能测试技术
性能测试技术
 
Load runner测试技术
Load runner测试技术Load runner测试技术
Load runner测试技术
 
J2 ee性能测试
J2 ee性能测试J2 ee性能测试
J2 ee性能测试
 
面向对象的Js培训
面向对象的Js培训面向对象的Js培训
面向对象的Js培训
 
Flex3中文教程
Flex3中文教程Flex3中文教程
Flex3中文教程
 
开放源代码的全文检索Lucene
开放源代码的全文检索Lucene开放源代码的全文检索Lucene
开放源代码的全文检索Lucene
 
基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍
 
Lucene In Action
Lucene In ActionLucene In Action
Lucene In Action
 
Lucene2 4学习笔记1
Lucene2 4学习笔记1Lucene2 4学习笔记1
Lucene2 4学习笔记1
 
Lucene2 4 Demo
Lucene2 4 DemoLucene2 4 Demo
Lucene2 4 Demo
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
 
Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析
 
7 面向对象设计原则
7 面向对象设计原则7 面向对象设计原则
7 面向对象设计原则
 
10 团队开发
10  团队开发10  团队开发
10 团队开发
 
9 对象持久化与数据建模
9  对象持久化与数据建模9  对象持久化与数据建模
9 对象持久化与数据建模
 
8 Uml构架建模
8  Uml构架建模8  Uml构架建模
8 Uml构架建模
 

Jdbc中驱动加载的过程分析(下)

  • 1. JDBC 中驱动加载的过程分析(下) 江苏 无锡 缪小东 本篇主要用几个开源数据库的驱动讲述驱动是如何加载的,以及“可插拔”机制等。 由于文章篇幅有限,本文章并不是专门研究开源源代码!因此我们仅研究那些与数据库驱动加载直 接相关的方法。在下面的几个开源软件的驱动中,我们主要关注驱动类的 getConnection()方法。 一、几个开源数据库的驱动类 以下第一个是 smallsql 中驱动类 SSDriver 的源代码: package smallsql.database; import java.sql.*; import java.util.Properties; public class SSDriver implements Driver { static SSDriver drv; static { try{ drv = new SSDriver(); java.sql.DriverManager.registerDriver(drv); }catch(Throwable e){} } public Connection connect(String url, Properties info) throws SQLException { if(!acceptsURL(url)) return null; …… return new SSConnection( (idx > 0) ? url.substring(idx+1) : null); } …… } 从上面红色的部分可以看到:这是一个静态语句块(static block) ,这意味着该语句是在类构造完成 前完成的(关于语句块的加载请阅读《Think in java》。即调用 class.forName(“smallsql.database.SSDriver”)语句 ) 时,会首先创建一个 SSDriver 的实例,并且将其向驱动管理器(DriverManager)注册。这样就完成驱动的注 册了。 从上面的蓝色的代码可以看出:驱动的连接方法返回的是一个具体的 SSConnection 对象。而在前面 研究的 Driver 接口中返回的是 Connection 接口,这是不茅盾的,SSConnection 对象实现了 Connection 接口。 再下面一个是 HSqlD 中的驱动类的源代码: package org.hsqldb; import java.sql.*; import java.util.Properties; import org.hsqldb.jdbc.jdbcConnection; import org.hsqldb.persist.HsqlDatabaseProperties; import org.hsqldb.persist.HsqlProperties; public class jdbcDriver implements Driver { 1
  • 2. public Connection connect(String url, Properties info) throws SQLException { return getConnection(url, info); } public static Connection getConnection(String url, Properties info) throws SQLException { HsqlProperties props = DatabaseURL.parseURL(url, true); if (props == null) { throw new SQLException(Trace.getMessage(Trace.INVALID_JDBC_ARGUMENT)); } else if (props.isEmpty()) { return null; } props.addProperties(info); return new jdbcConnection(props); } static { try { DriverManager.registerDriver(new jdbcDriver()); } catch (Exception e) {} } } 蓝色的依然是建立连接的部分,依然返回某个具体的实现 java.sql.Connection 接口的对象。是设计 模式中的哪个工厂啊(一般工厂、抽象工厂、工厂方法还是什么都不是啊) ! 红色的同样是一个静态语句块,同样完成该驱动的注册。 两个开源数据库的驱动竟然如此相似,是不是其它的就不一样呢!看下面是 mckoi 中的驱动类: package com.mckoi; public class JDBCDriver extends com.mckoi.database.jdbc.MDriver { static { com.mckoi.database.jdbc.MDriver.register(); } public JDBCDriver() { super(); // Or we could move driver registering here... } } 红色的部分又是完成相同的工作――在类装载完成前向驱动管理器注册驱动,只不过这次是调用 MDriver 的 register 方法罢了。那么该驱动建立连接是否也一样呢,当然一样啦!不信你看下面的代码: package com.mckoi.database.jdbc; …… public class MDriver implements Driver { …… private static boolean registered = false; public synchronized static void register() { if (registered == false) { try { 2
  • 3. java.sql.DriverManager.registerDriver(new MDriver()); registered = true; }catch (SQLException e) { e.printStackTrace(); } } } public Connection connect(String url, Properties info) throws SQLException { if (!acceptsURL(url)) { return null; } DatabaseInterface db_interface; int row_cache_size; int max_row_cache_size; …… MConnection connection = new MConnection(url, db_interface, row_cache_size, max_row_cache_size); …… return connection; } } 从以上三个开源数据库驱动的源代码可以看出: 在调用 Class.forName(“XXXDriver”)时,完成了将具体 的驱动程序向 JDBC API 中驱动管理器的注册, 该注册方法在类构造完成前完成, 一般使用静态语句块。 在调用 DriverManager 的 getConnection 方法时,一般先在已注册的驱动中查找可以了解此 URL 的驱动, 然后调用该驱动的 connect 方法,从而建立连接,返回的连接都是一个实现 java.sql.Connection 接口的具 体类。下面是该过程的时序图。 二、JDBC 中驱动加载的时序图 以上是 JDBC 中驱动加载的时序图。时序图主要有以下 7 个动作: 1. 客户调用 Class.forName(“XXXDriver”)加载驱动。 2. 此时此驱动类首先在其静态语句块中初始化此驱动的实例, 3. 再向驱动管理器注册此驱动。 3
  • 4. 4. 客户向驱动管理器 DriverManager 调用 getConnection 方法, 5. DriverManager 调用注册到它上面的能够理解此 URL 的驱动建立一个连接, 6. 在该驱动中建立一个连接,一般会创建一个对应于数据库提供商的 XXXConnection 连接对象, 7. 驱 动 向 客 户 返 回 此 连 接 对 象 , 不 过 在 客 户 调 用 的 getConnection 方 法 中 返 回 的 为 一 个 java.sql.Connection 接口,而具体的驱动返回一个实现 java.sql.Connection 接口的具体类。 以上就是驱动加载的全过程。由此过程我们可以看出 JDBC 的其它一些特点。 三、JDBC 的架构 在《教你建立简单 JDBC 程序》一篇中,讲述了一般 JDBC 的几个步骤。通过本篇的介绍,我将此 程序分为以下几部分: 上图中,蓝色的即为本章前面介绍的 JDBC 驱动加载的细节部分。看看下面的部分:左面的很明显 吧!是 java.sql 包中的接口吧!它是抽象的!右边呢?通过驱动管理器 DriverManager 得到的是一个实现 java.sql.Connection 接口的具体类吧! (不知道啊!前面不是讲过了吗!)因此我们可以可以注意到左右分 别是抽象的和具体的。 这种抽象和具体的连接是由 java 的 RTTI 支持的, ( 不懂可以阅读 《Think in java》。 ) 在接下来的结果集的处理 rs 也是抽象的吧! 因此,在写 JDBC 程序时,即使我们使用不同数据库提供商的数据库我们只要改变驱动类的地址, 和具体连接的 URL 及其用户名和密码,其它几乎不用任何修改,就可以完成同样的工作!方便吧! 这意味着什么呢?我们其实是在针对抽象接口编程,只要知道接口的调用顺序,以及其中的主要方 法,我们就可以迅速学会 JDBC 编程了! 同时,我们只要对不同数据库提供商的驱动类使用 Class.forName(“XXXDriver”)就可以加载驱动, 其细节你根本不用关注――JDBC Framework 已经全为你搞定了!应用程序对于不同提供商的数据库是 无需太多改动的,因而其是“可插拔”的!整个 J2EE 就是一个高层的 API――抽象接口,用户可以使 4
  • 5. 用不同的产品提供商提供的产品,使用统一的 API,从而便于程序员学习! 谢谢大家!到此结束! 更多精彩请关注: http://blog.163.com/miaoxiaodong78/ 5