`
aids198311
  • 浏览: 59467 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

关于DriverManager与驱动

阅读更多
刚才无意中看到几篇讲DriverManager源码的文章,发现几点没有讲明白的地方。
这里重新说一下:
直接进入正题
Class.forName("com.mysql.jdbc.Driver");

这个玩意做了这些事情:
1.驱动的实现类:com.mysql.jdbc.Driver 里面的static块,调用DriverManger.registerDriver()来        注册自己
2.DriverManger自己初始化(仅第一次调用注册方法的时候调用一次)
3.把驱动封装成对象存到victor里面

第一点,每个驱动的实现类都必须明确的注册自己到DriverManger里面。
而且这个方法大都是放在static块里面的,所以forName一下就会执行了。

第二点,这个初始化并不是初始化com.mysql.jdbc.Driver这个驱动,而是初始化自带的驱动
如:sun.jdbc.odbc.JdbcOdbcDriver。看代码也能发现,初始化与传递进来的驱动一毛钱关系都没有。
    public static synchronized void registerDriver(java.sql.Driver driver)
	throws SQLException {
	if (!initialized) {
            //这里初始化
	    initialize();
	}
   ....................

最后会调用到
 private static void loadInitialDrivers() {
        String drivers;
        try {
             //这里返回的是null
	    drivers = (String) java.security.AccessController.doPrivileged(
		new sun.security.action.GetPropertyAction("jdbc.drivers"));
        } catch (Exception ex) {
            drivers = null;
        }
	 DriverService ds = new DriverService();
         //在这里会初始化odbc驱动
	 java.security.AccessController.doPrivileged(ds);		
         println("DriverManager.initialize: jdbc.drivers = " + drivers);
        if (drivers == null) {
            return;
        }
}

java.security.AccessController.doPrivileged(ds) 这块代码是native的,搞不清除是干嘛的,于是写了一个代码debug看了一下,程序如下:
public static void main(String[] args) {
        DriverManager.setLogWriter(new PrintWriter(System.out));
        try {
            Class.forName("com.mysql.jdbc.ReplicationDriver");
            Class.forName("com.mysql.jdbc.Driver");
            Class.forName("org.apache.commons.dbcp.PoolingDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

注册三个驱动程序,并把DriverManger的log输出到控制台,打上断点debug了一下
发现在
java.security.AccessController.doPrivileged(ds)
方法里面,会调用DriverManager.registerDriver,而且传递的参数Driver是sun.jdbc.odbc.JdbcOdbcDriver
所以可以肯定,initialized()方法是用来初始化自带的驱动程序。显然,后面2个驱动的注册,不会再次初始化DriverManager
控制台的输出如下:
引用

JdbcOdbcDriver class loaded
registerDriver: driver[className=sun.jdbc.odbc.JdbcOdbcDriver,sun.jdbc.odbc.JdbcOdbcDriver@1b09468]
registerDriver: driver[className=com.mysql.jdbc.Driver,com.mysql.jdbc.Driver@10e790c]
DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized
registerDriver: driver[className=com.mysql.jdbc.NonRegisteringReplicationDriver,com.mysql.jdbc.NonRegisteringReplicationDriver@1551d7f]
registerDriver: driver[className=org.apache.commons.dbcp.PoolingDriver,org.apache.commons.dbcp.PoolingDriver@b8deef]



顺带说一下ClassLoader
驱动的实现类都是用下面这个classLoader来加载的
    /* Returns the caller's class loader, or null if none */
    private static native ClassLoader getCallerClassLoader();


虽然又是一个native方法,但是顾名思义可以知道,这个方法返回的是调用者的classLoader,如:我在Class A里面调用了DriverManager.getConnection方法,那么驱动类就是由加载A的classLoader来加载。为啥要这样?
看一下DriverManager就明白了。
   public static void main(String[] args) {
        System.out.println(DriverManager.class.getClassLoader());
   }

控制台输出null
表明DriverManager的classLoader是相当NB的bootstrap ClassLoader
而我们自己写的类一般都是由systemClassloader加载的。
如果在DriverManager直接class.forName("com.mysql.jdbc.ReplicationDriver"),就表示要让bootstrap ClassLoader来加载jdk/lib目录下的com.mysql.jdbc.ReplicationDriver,可能么??明显不在那里,而是在classpath目录下。
所以要这么来class.forName("com.mysql.jdbc.ReplicationDriver",true, callerClassLoader)

另外如果getCallerClassLoader()返回了空,则会获取当前线程上下文的classLoader
          if(callerCL == null) {
	      callerCL = Thread.currentThread().getContextClassLoader();
	   }   

ContextClassLoader可以设置,默认的都是systemClassLoader
ContextClassLoader在web容器里面用到的比较多,它可以让父classLoader访问到子的classLoader的class,如这个驱动程序
就是,在父classLoader(bootstrap)加载的类里面,访问到了子classLoader(SystemClassLoader)才能加载的类(com.mysql.jdbc.ReplicationDriver)。
分享到:
评论
2 楼 diyunpeng 2012-06-18  
JdbcOdbcDriver class loaded
registerDriver: driver[className=sun.jdbc.odbc.JdbcOdbcDriver,sun.jdbc.odbc.JdbcOdbcDriver@1b09468]
registerDriver: driver[className=com.mysql.jdbc.Driver,com.mysql.jdbc.Driver@10e790c]
DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized
registerDriver: driver[className=com.mysql.jdbc.NonRegisteringReplicationDriver,com.mysql.jdbc.NonRegisteringReplicationDriver@1551d7f]
registerDriver: driver[className=org.apache.commons.dbcp.PoolingDriver,org.apache.commons.dbcp.PoolingDriver@b8deef]

驱动不是5.1.20吧,在20这个版本上,默认通过服务发现机制就把驱动加载上了。另外
1.   public static synchronized void registerDriver(java.sql.Driver driver)  
2.throws SQLException {  
3.if (!initialized) {  
4.           //这里初始化  
5.    initialize();  
6.}  

这个在DriverManger里面也没有,你的是从哪里找到的?

DriverManager.setLogWriter(new PrintWriter(System.out));  后默认就加载类初始化函数了,就把驱动加载上了,你设置Logger也没用啊。
1 楼 worldmaomao 2011-08-03  
毛哥友情帮你顶顶!

相关推荐

    DriverManager 驱动加载管理程序

    DriverManager提供的符号链查看功能可以帮助开发者追踪驱动的加载顺序,以及它们如何与其他内核组件交互,这对于理解和调试复杂的驱动生态系统至关重要。 5. **物理内存浏览** 为了进行低级别的内存调试和分析,...

    java数据库连接DriverManager

    - 安全性检查:对于不可信的驱动,`DriverManager`只在加载驱动的类加载器与发起连接请求的代码相同的情况下使用。 - 如果多个驱动都能连接,`DriverManager`会选择第一个成功建立连接的驱动,这意味着驱动的测试...

    通过DriverManager类提供的方法控制日志输出

    总结来说,虽然`DriverManager`类自身不直接提供日志控制,但我们可以通过调整数据库驱动的配置、使用Java内置的日志框架或者集成第三方日志库来实现日志输出的控制。理解这些机制有助于我们在开发过程中更好地监控...

    JDBC DriverManager.registerDriver(new Driver());

    它维护了一个驱动程序列表,当应用程序请求与数据库建立连接时,`DriverManager`会根据提供的URL找到合适的驱动程序,并使用该驱动程序创建连接。 **registerDriver()** 方法是`DriverManager`类的一个静态方法,它...

    驱动管家DriverManagerv1.0中文绿色免费版

    驱动管家DriverManager v1.0中文绿色免费版是一款专为用户设计的系统工具,主要功能集中在硬件驱动程序的管理上,包括驱动升级、驱动备份和驱动还原三个方面。这些功能对于保持计算机系统的稳定性和优化硬件性能至关...

    java数据库驱动包

    安装JDBC驱动后,可以通过`Class.forName()`方法加载驱动,并使用`DriverManager.getConnection()`建立与MySQL服务器的连接。 2. **Oracle JDBC驱动**: Oracle数据库是商业级的、高性能的数据库系统。Oracle提供...

    达蒙数据库jdbc驱动

    **达蒙数据库与JDBC驱动概述** 达蒙数据库(Dameng Database)是一款源自中国的高性能、高可用性的关系型数据库管理系统,特别适用于企业级应用。它支持标准的SQL语法,提供了丰富的数据类型和强大的事务处理能力,...

    java数据库驱动jar包

    在Java中,JDBC驱动程序提供了一个标准的API,使得开发人员能够使用SQL语句与各种数据库进行交互。这个压缩包包含了用于连接到SQL Server 2005的Java驱动以及JDTS驱动,它们都是实现JDBC规范的不同类型。 首先,让...

    sqlserver驱动jar

    在Java环境中,为了能够与SQL Server进行数据交互,我们需要一个兼容的 JDBC (Java Database Connectivity) 驱动程序,通常以jar(Java Archive)文件的形式存在。本文将深入探讨SQL Server驱动jar的相关知识点,...

    oracle驱动包和mysql驱动包

    Oracle驱动包和MySQL驱动包是数据库连接的重要组成部分,它们使得Java或其他编程语言能够与数据库进行交互,执行查询、更新和事务处理等操作。在本文中,我们将深入探讨这两个驱动包的特点、用途以及如何在实际开发...

    MySQL驱动 5.7 ,8.2

    `mysql-connector-java-8.0.22.zip`包含的是适用于MySQL 8.2的Java驱动,8.0.x版本的驱动与MySQL 8.x服务器版本相匹配。解压后,同样将`mysql-connector-java-x.x.x.jar`文件添加到Java项目类路径,以便进行数据库...

    sql2008R2驱动包

    而"sql2008R2驱动包"则指的是用于连接Java应用程序与SQL Server 2008 R2数据库的驱动程序。这个驱动包主要包含两个文件:sqljdbc.jar和sqljdbc4.jar,它们是Microsoft提供的Java Database Connectivity (JDBC) 驱动...

    驱动打包下载.zip

    这些JDBC驱动文件的使用方式大致相同,都需要在Java程序中通过`Class.forName()`加载对应的驱动类,然后使用`DriverManager.getConnection()`方法创建数据库连接。例如: ```java // 加载驱动 Class.forName(...

    JDBC驱动加载分析

    JDBC驱动加载是一个关键步骤,它决定了Java应用程序能否成功地与数据库建立连接。在本例中,我们将探讨sun提供的JDBC-ODBC桥接驱动的加载过程。这种驱动方式通常用于像Microsoft Access这样的数据库,需要配置数据源...

    数据库驱动jar包 驱动

    本文将详细介绍关于SQL Server 2000、2005以及MySQL数据库的驱动,以及如何使用这些驱动来建立数据库连接。 首先,让我们关注SQL Server 2000和2005的驱动。微软的SQL Server是一款广泛使用的商业关系型数据库管理...

    神通数据库java连接驱动.zip

    在Java开发环境中,为了实现Java程序与神通数据库的交互,我们需要使用特定的Java连接驱动,也就是JDBC驱动。本压缩包“神通数据库java连接驱动.zip”中包含了用于Java应用程序连接神通数据库所需的驱动文件。 首先...

    mysql驱动jar包.rar

    MySQL驱动jar包是Java应用程序与MySQL数据库进行交互的重要组件,它是Java Database Connectivity (JDBC) 驱动的一部分。在Java编程中,当你需要连接到MySQL数据库执行查询、更新或其他数据库操作时,这个驱动程序...

    MySQL的驱动包.rar

    MySQL驱动包是用于Java应用程序与MySQL数据库之间进行通信的关键组件,它遵循Java Database Connectivity (JDBC) API标准。在Java编程中,当你需要连接到MySQL数据库执行查询、更新或者其他数据库操作时,就需要引入...

    GYWDK-DriverManager使用说明1

    该库主要包含两个导出函数,用于与驱动相关的操作,如安装、启动、停止和卸载。以下是这两个关键函数的详细说明: 1. `GYWDKSetDllPath` 函数: - 函数原型:`__declspec(dllexport) int GYWDKSetDllPath(const ...

    Kingbase_v8_R3JDBC驱动.zip

    Kingbase_v8_R3JDBC驱动属于Type 4,它是纯Java实现的,直接与数据库服务器通信,无需依赖特定的数据库API或者中间层软件。 使用Kingbase_v8_R3JDBC驱动时,开发者需要注意以下几点: 1. 确保Java环境和JDBC驱动...

Global site tag (gtag.js) - Google Analytics