JDBC加载数据库驱动源码分析

       今天在看JDBC编程的时候有个疑惑:为什么加载数据库驱动只需要下面这样的一句?它把Driver的Class对象创建出来却没有引用,这到底是几个意思?怎么看起来跟后面的代码完全是独立的,但是把它删除又会报错。

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

 

       首先来看看Class.forName(String className)这个方法,虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都会有一个Class对象。运行程序时,JVM首先检查是否所要加载的类对应的Class对象已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。每个数组被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都能共享该Class对象。一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。

       如何得到Class的对象呢?常用的有两种方法:

       1.调用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。例如:

Object obj = new Object();
Class clazz = obj.getClass();

      2.使用Class类中的静态forName()方法获得与字符串对应的Class对象,当执行下面的方法之后,该被加载的类中的static初始化块将会被执行。

Class clazz = Class.forName("class java.lang.Object");

 

下面进入源码分析部分:

       既然加载的是com.mysql.jdbc.Driver这个类,那么就先看这个类,它实现了java.sql.Driver这个接口,java.sql.Driver是每个驱动程序类必须实现的接口。DriverManager会试着加载尽可能多的它可以找到的驱动程序,然后,对于任何给定连接请求,它会让每个驱动程序依次试着连接到目标URL。在加载某一Driver类时。它应该创建自己的实例并向DriverManager注册该实例。下面是com.mysql.jdbc.Driver中的静态初始化块,也就是说执行Class.forName(“com.mysql.jdbc.Driver”)之后,调用的就是这个静态初始化块中的方法。

    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

 

        这里面核心的就是java.sql.DriverManager.registerDriver(new Driver())这个方法是jdk中sql包下的DriverManager类的静态方法,它接收的参数类型是java.sql.Driver,就是因为所有的数据库驱动程序都实现了java.sql.Driver接口,所以可以把com.mysql.jdbc.Driver类传进去。这也是为什么不同的数据库驱动可以往同一个DriverManager中注册的原因。

    public static synchronized void registerDriver(java.sql.Driver driver)
        throws SQLException {

        registerDriver(driver, null);
    }

       继续点进去。

 

       来到了registerDriver(java.sql.Driver driver,DriverAction da);其实就是把当前的JDBC驱动加入到registeredDrivers中。

    public static synchronized void registerDriver(java.sql.Driver driver,
            DriverAction da)
        throws SQLException {

        /* Register the driver if it has not already been added to our list */
        if(driver != null) {
            registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
        } else {
            // This is for compatibility with the original DriverManager
            throw new NullPointerException();
        }

        println("registerDriver: " + driver);

    }

 

       看看registeredDrivers是DriverManager类中的静态变量,是一个用来存放已经注册的JDBC驱动的List。

    // List of registered JDBC drivers
    private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();

       

        这就是一个数据库驱动加载并注册到DriverManager中的全部过程。

 

      但是我有一个问题一直没有想明白,DriverManager是什么时候被加载到JVM中的?是怎么被初始化的?来一个简版的Driver与DriverManager就很清晰了。

       DriverManagerTest类,list一定要初始化,如果没有初始化,list的初始值就是null,空指针你懂的。

public class DriverManagerTest {

	static {
		System.out.println("DriverManagerTest类加载完毕。。。");
	}
	
	// 一定要初始化
	private static List<String> list = new ArrayList<>();

	public static void addElement() {
		list.add("str1");
	}

	public static String getElement() {
		return list.get(0);
	}

}

        

       DriverTest类

public class DriverTest {

	static {
		DriverManagerTest.addElement();
		System.out.println("DriverTest的静态初始化块执行完毕。。。。");
	}
	
	public static void main(String[] args) throws Exception{
		Class.forName("com.xiaoshan.hr.entity.DriverTest");
		System.out.println(DriverManagerTest.getElement());
	}
	
}

       运行结果:

DriverManagerTest类加载完毕。。。
DriverTest的静态初始化块执行完毕。。。。
str1

        程序分析:

       Class.forName("com.xiaoshan.hr.entity.DriverTest");加载了DriverTest这个类到JVM中,随后执行DriverTest的静态初始化块的方法,在DriverTest的静态初始化块调用了DriverManagerTest的addElement()。噔噔噔!此时,DriverManagerTest类的静态初始化块已经执行了,说明此时DriverManagerTest类已经被加载了,然后再调用DriverManagerTest的静态方法,往它的静态成员list中添加了一个元素。最终通过静态方法getElement()可以看到list中已经加入了一个元素str1。这个就是DriverManagerTest的加载过程。所以上面的DriverManager在什么时候被加载道理是一毛一样的。

       最后,欢迎点赞关注,有问题?下方留言。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值