JDBC入门

从Class.forName说起

查看com.mysql.jdbc.Driver的注释,当一个Driver类被加载的时候,它需要创建自己的一个实例,并且注册到DriverManager中。
Class.forName("com.mysql.jdbc.Driver")会触发类加载,及静态块的初始化。

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

另外,DriverManager有个静态块,通过jdbc.properties 及ServiceLoader注册Driver。

static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
}

private static void loadInitialDrivers() {
        String drivers;
// 通过系统配置注册
        try {
            drivers = AccessController.doPrivileged(new PrivilegedAction() {
                public String run() {
                    return System.getProperty("jdbc.drivers");
                }
            });
        } catch (Exception ex) {
            drivers = null;
        }
// 通过ServiceLoader注册
        AccessController.doPrivileged(new PrivilegedAction() {
            public Void run() {
                ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class);
                Iterator driversIterator = loadedDrivers.iterator();
                try{
                    while(driversIterator.hasNext()) {
                        driversIterator.next();
                    }
                } catch(Throwable t) {
                }
                return null;
            }
        });

查看mysql-connector-java-5.1.39.jar!/META-INF/services/java.sql.Driver文件内容

com.mysql.jdbc.Driver
com.mysql.fabric.jdbc.FabricMySQLDriver

注:AccessController、ServiceLoader自行Google。

Driver的处理

将MySQL的Driver对象放入到java.sql.DriverManager#registeredDrivers中,它是一个CopyOnWriteArrayList对象。

    public static synchronized void registerDriver(java.sql.Driver driver,
            DriverAction da)
        throws SQLException {
        if(driver != null) {
            registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
        } else {
            // This is for compatibility with the original DriverManager
            throw new NullPointerException();
        }
    }

打印Driver

public class DriverTest {
    public static void main(String[] args) {
        Enumeration drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()){
            System.out.println(drivers.nextElement().toString());
        }
    }
}

com.mysql.jdbc.Driver@6193b845
com.mysql.fabric.jdbc.FabricMySQLDriver@433c675d
org.h2.Driver@439f5b3d
com.alibaba.druid.proxy.DruidDriver@533ddba
com.alibaba.druid.mock.MockDriver@aec6354

Connection获取

java.sql.DriverManager#getConnection(java.lang.String, java.util.Properties, java.lang.Class)

       for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
//成功获取连接,就返回。
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }
            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }
        }
// 最后没有找到抛出异常
        // if we got here nobody could connect.
        if (reason != null)    {
            println("getConnection failed: " + reason);
            throw reason;
        }

在获取连接的时候,会获取第一个能成功连接的Connection,如果注册多个MySQL Driver,仅仅会使用第一个。

参考

http://dustin.iteye.com/blog/44291
http://www.dengshenyu.com/java/2017/06/24/jdbc-basic.html

你可能感兴趣的:(JDBC入门)