Class.forName("com.mysql.jdbc.Driver") 到底做了什么?

一句话总结:将mysql驱动注册到DriverManager中去。

那么为什么可以通过这行代码实现注册driver功能呢?

答:

  1. Class.forName() 方法要求JVM查找并加载指定的类到内存中
  2. 将"com.mysql.jdbc.Driver" 当做参数传入,就是告诉JVM,去"com.mysql.jdbc"这个路径下找Driver类,将其加载到内存中。
  3. 由于JVM加载类文件时会执行其中的静态代码块,从Driver类的源码中可以看到该静态代码块执行的操作是:将mysql的driver注册到系统的DriverManager中

我们首先看forName方法的源码:

public static Class<?> forName(String className) throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

我们可以看到返回值是 Class<?>,即我们将mysql的驱动类→driver类加载到了
内存中。
我们知道,当类被加载到内存中时,会首先执行类的静态代码块中的内容,那我们接下来就看看Driver类的源码,看看它被加载到内存中时,到底执行了什么内容。
我们找到com.mysql.jdbc.Driver类:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
        	//1. 新建一个mysql的driver对象
        	//2. 将这个对象注册到DriverManager中
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

可以看到,静态代码块中执行的内容是:新建一个msql的driver对象,并将其注册到DriverManager中去。

接下来我们再看看这个DriverManager.registerDriver 方法,先看这个方法的说明:

  1. 将参数中的driver注册到DriverManager中。
  2. 新加载的驱动类,应该通过调用这个方法来将自己注册到DriverManager中。
  3. 如果这个驱动已经被注册,那么将不会做任何动作。
/**
     * Registers the given driver with the {@code DriverManager}.
     * A newly-loaded driver class should call
     * the method {@code registerDriver} to make itself
     * known to the {@code DriverManager}. If the driver is currently
     * registered, no action is taken.
     */
	public static void registerDriver(java.sql.Driver driver) throws SQLException {
		//它实际调用了自身的registerDriver方法
        registerDriver(driver, null);
    }

继续看这个registerDriver(driver, null);方法

// registeredDrivers 是一个支持并发的arraylist
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
......
public static 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 中去。这是一个支持并发情况的特殊ArrayList
            registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
        } else {
            // This is for compatibility with the original DriverManager
            throw new NullPointerException();
        }

        println("registerDriver: " + driver);

    }

registeredDrivers.addIfAbsent(new DriverInfo(driver, da)) 表示:如果该驱动尚未注册,那么将他添加到 registeredDrivers 这个并发链表中去中去。CopyOnWriteArrayList。

此时,Class.forName(“com.mysql.jdbc.Driver”) 的工作就完成了,这一行代码的工作就是:将mysql驱动注册到DriverManager中去

DriverManager.getConnection方法分析

注册的DriverManager中之后,我们就可以 通过DriverManager的getConnection方法获得mysql的连接了:

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");

接下来我们在看看这个getConnection方法:

	@CallerSensitive
    public static Connection getConnection(String url,
        String user, String password) throws SQLException {
        ......
        return (getConnection(url, info, Reflection.getCallerClass()));
    }

同样,调用了自身的 getConnection方法;继续往里看

private static Connection getConnection(
        String url, java.util.Properties info, Class<?> caller) throws SQLException {
        ......
        for (DriverInfo aDriver : registeredDrivers) {
			......
            Connection con = aDriver.driver.connect(url, info);
			......
		}
    }

可以看到它对上文提到的特殊ArrayList进行了遍历,调用了connect(url, info); 方法,这是一个接口,由各个不同的驱动自己实现。

    /**
     * Attempts to make a database connection to the given URL.
     * The driver should return "null" if it realizes it is the wrong kind
     * of driver to connect to the given URL.  This will be common, as when
     * the JDBC driver manager is asked to connect to a given URL it passes
     * the URL to each loaded driver in turn.
     */
    Connection connect(String url, java.util.Properties info)
        throws SQLException;

到此为止,我们就获得了connection对象,现在就可以对数据库进行操作了。

  • 37
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值