JDBC 驅動加載註冊過程分析

以MySQL數據庫提供的驅動com.mysql.jdbc.Driver爲例:java

1、Driver接口mysql

一、首先咱們看一下JDBC標準定義的Driver接口:
     sql

package java.sql;

public interface Driver {
	//它主要是使用指定的URL(如com.mysql.jdbc.Driver)和與具體提供商相關的信息創建一個鏈接。
    Connection connect(String url, java.util.Properties info)
        throws SQLException;
		
    boolean acceptsURL(String url) throws SQLException;
	
    DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info)
			 throws SQLException;
    int getMajorVersion();    //返回驅動的主版本號
    int getMinorVersion();	  //返回驅動的次版本號
    boolean jdbcCompliant();  //是否兼容於JDBC標準
}
  
以上就是JDBC中的Driver接口,它是任何數據庫提供商的驅動類必須實現的接口,它之因此是一個接口,就是OO中常常談到的「依賴倒轉原則(DIP-Dependence Inverse Principle)」的具體應用了!在DriverManager類中能夠看到:它使用的驅動都是Driver接口,從而依賴於高層,不依賴於實現。這樣就使得JDBC Framework能夠管理和維護不一樣JDBC提供商的數據庫驅動,從而不用改變上層的代碼,由於它們都是基於JDBC所定義標準的實現。

二、MySQL數據庫提供商實現的Driver類源碼:
     數據庫

package com.mysql.jdbc;

import java.sql.SQLException;

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!");
		}
	}

	public Driver() throws SQLException {
		// Required for Class.forName().newInstance()
	}
}

從MySQL的Driver實現中,咱們能夠看到當咱們調用
Class.forName("com.mysql.jdbc.Driver");

時,會執行上面的靜態代碼塊,從而加載註冊咱們提供的數據庫驅動。

2、DriverManager驅動管理器ide

DriverManager類是整個JDBC的起點!利用它能夠加載並註冊咱們的驅動,建立鏈接,從而完成後續的操做。
ui

package java.sql;

import sun.misc.Service;

import java.util.Iterator;

public class DriverManager {

    final static SQLPermission SET_LOG_PERMISSION = 
        new SQLPermission("setLog");

    
    public static java.io.PrintWriter getLogWriter() {
	    return logWriter;
    }

   
    public static void setLogWriter(java.io.PrintWriter out) {

	SecurityManager sec = System.getSecurityManager();
	if (sec != null) {
	    sec.checkPermission(SET_LOG_PERMISSION);
	}
	    logStream = null;
	    logWriter = out;
    }

    public static Connection getConnection(String url, 
	java.util.Properties info) throws SQLException {
 
	ClassLoader callerCL = DriverManager.getCallerClassLoader();

        return (getConnection(url, info, callerCL));
    }

    
    public static Connection getConnection(String url, 
	String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();

	ClassLoader callerCL = DriverManager.getCallerClassLoader();

	if (user != null) {
	    info.put("user", user);
	}
	if (password != null) {
	    info.put("password", password);
	}

        return (getConnection(url, info, callerCL));
    }

    public static Connection getConnection(String url) 
	throws SQLException {

        java.util.Properties info = new java.util.Properties();

	ClassLoader callerCL = DriverManager.getCallerClassLoader();

        return (getConnection(url, info, callerCL));
    }

    public static Driver getDriver(String url) 
	throws SQLException {
	java.util.Vector drivers = null;

        println("DriverManager.getDriver(\"" + url + "\")");

        if (!initialized) {
            initialize();
        }

	synchronized (DriverManager.class){ 
            
	    drivers = readDrivers;  
        }

	ClassLoader callerCL = DriverManager.getCallerClassLoader();

        for (int i = 0; i < drivers.size(); i++) {
            DriverInfo di = (DriverInfo)drivers.elementAt(i);
	    
            if ( getCallerClass(callerCL, di.driverClassName ) != 
		 di.driverClass ) {
                println("    skipping: " + di);
                continue;
            }
            try {
                println("    trying " + di);
		if (di.driver.acceptsURL(url)) {
		    
                    println("getDriver returning " + di);
                    return (di.driver);
                }
            } catch (SQLException ex) {
		
            }
        }

        println("getDriver: no suitable driver");
        throw new SQLException("No suitable driver", "08001");
    }
    
    //向DriverManager註冊指定的驅動
    public static synchronized void registerDriver(java.sql.Driver driver) 
    throws SQLException {
        //註冊驅動以前保證已經初始化
        if (!initialized) {
	    initialize();
	}
      
        //建立一個驅動信息類,用於記錄驅動的各類信息
	DriverInfo di = new DriverInfo();

	di.driver = driver;
	di.driverClass = driver.getClass();
	di.driverClassName = di.driverClass.getName();
        
        //將驅動信息加入一個驅動的Vector中,這個Vector用於記錄註冊的多個驅動
        writeDrivers.addElement(di); 
	println("registerDriver: " + di);
	
	readDrivers = (java.util.Vector) writeDrivers.clone();

    }

    //從DriverManager中取消註冊某個驅動
    public static synchronized void deregisterDriver(Driver driver) 
	throws SQLException {
	
	ClassLoader callerCL = DriverManager.getCallerClassLoader();
	println("DriverManager.deregisterDriver: " + driver);
    
	int i;
	DriverInfo di = null;
	for (i = 0; i < writeDrivers.size(); i++) {
	    di = (DriverInfo)writeDrivers.elementAt(i);
	    if (di.driver == driver) {
		break;
	    }
	}
	
	if (i >= writeDrivers.size()) {
	    println("    couldn't find driver to unload");
	    return;
	}
      
	
	if (getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
	    throw new SecurityException();
	}
      
	//在以上全部操做後能夠刪除此驅動了
	writeDrivers.removeElementAt(i);

	readDrivers = (java.util.Vector) writeDrivers.clone();        
    }

    //獲得當前全部加載的驅動枚舉
    public static java.util.Enumeration<Driver> getDrivers() {
        java.util.Vector<Driver> result = new java.util.Vector<Driver>();
	java.util.Vector drivers = null; 

        if (!initialized) {
            initialize();
        }

 	synchronized (DriverManager.class){ 
           
	    drivers  = readDrivers;    
       }

      
	ClassLoader callerCL = DriverManager.getCallerClassLoader();

        //遍歷全部的驅動
        for (int i = 0; i < drivers.size(); i++) {
            //獲得某個具體的驅動
            DriverInfo di = (DriverInfo)drivers.elementAt(i);
	    
            //假如調用者沒有許可加載此驅動時,忽略該驅動
            if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
                println("    skipping: " + di);
                continue;
            }
            //將能夠加載的驅動加入返回的結果集
             result.addElement(di.driver);
        }
        //返回結果集
        return (result.elements());
    }

    public static void setLoginTimeout(int seconds) { 
        loginTimeout = seconds;
    }

   
    public static int getLoginTimeout() {
        return (loginTimeout);
    }

   
    public static void setLogStream(java.io.PrintStream out) {
        
        SecurityManager sec = System.getSecurityManager();
        if (sec != null) {
            sec.checkPermission(SET_LOG_PERMISSION);
        }

        logStream = out;
	if ( out != null )
	    logWriter = new java.io.PrintWriter(out);
	else
	    logWriter = null;
    }

    public static java.io.PrintStream getLogStream() {
        return logStream;
    }

    public static void println(String message) {
	synchronized (logSync) {
	    if (logWriter != null) {
		logWriter.println(message);
		
		
		logWriter.flush();
	    }
	}
    }

    
    private static Class getCallerClass(ClassLoader callerClassLoader, 
					String driverClassName) {
	Class callerC = null;

	try {
	    callerC = Class.forName(driverClassName, true, callerClassLoader);
	}
	catch (Exception ex) {
	    callerC = null;          
	}

	return callerC;
    }

    //初始化方法中完成加載全部系統提供的驅動的方法
    private static void loadInitialDrivers() {
        String drivers;
	
        try {
                //獲得系統屬性"jdbc.drivers"對應的驅動的驅動名,須要許可
                drivers = (String) java.security.AccessController.doPrivileged(
		new sun.security.action.GetPropertyAction("jdbc.drivers"));
        } catch (Exception ex) {
            drivers = null;
        }
        
      
	 DriverService ds = new DriverService();

	
	 java.security.AccessController.doPrivileged(ds);		
	        
         println("DriverManager.initialize: jdbc.drivers = " + drivers);
        if (drivers == null) {
            return;
        }
        while (drivers.length() != 0) {
            //系統屬性"jdbc.drivers"可能有多個數據庫驅動,這些驅動的名字是以":"分隔開的,將以':"分隔的驅動
            //依次遍歷,而後調用Class.forName加載
            int x = drivers.indexOf(':');
            String driver;
            if (x < 0) {
                driver = drivers;
                drivers = "";
            } else {
                driver = drivers.substring(0, x);
                drivers = drivers.substring(x+1);
            }
            if (driver.length() == 0) {
                continue;
            }
            try {
                println("DriverManager.Initialize: loading " + driver);
                Class.forName(driver, true,
			      ClassLoader.getSystemClassLoader());
            } catch (Exception ex) {
                println("DriverManager.Initialize: load failed: " + ex);
            }
        }
    }


    private static Connection getConnection(
	String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
	java.util.Vector drivers = null;
     
	synchronized(DriverManager.class) {	 
	 
	  if(callerCL == null) {
	      callerCL = Thread.currentThread().getContextClassLoader();
	   }    
	} 
	 
	if(url == null) {
	    throw new SQLException("The url cannot be null", "08001");
	}
    
	println("DriverManager.getConnection(\"" + url + "\")");
    
	if (!initialized) {
	    initialize();
	}

	synchronized (DriverManager.class){ 
           
	    drivers = readDrivers;  
        }

	//遍歷當前的全部驅動,並視圖創建鏈接
	SQLException reason = null;
	for (int i = 0; i < drivers.size(); i++) {
	    DriverInfo di = (DriverInfo)drivers.elementAt(i);
      
	    //加入調用者沒有許可加載該類變忽略
	    if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
		println("    skipping: " + di);
		continue;
	    }
	    try {
		println("    trying " + di);
                //調用某個驅動的鏈接方法創建鏈接
                Connection result = di.driver.connect(url, info);
		if (result != null) {
		    //在創建鏈接後打印鏈接信息且打印鏈接
		    println("getConnection returning " + di);
		    return (result);
		}
	    } catch (SQLException ex) {
		if (reason == null) {
		    reason = ex;
		}
	    }
	}
    
	
	if (reason != null)    {
	    println("getConnection failed: " + reason);
	    throw reason;
	}
    
	println("getConnection: no suitable driver found for "+ url);
	throw new SQLException("No suitable driver found for "+ url, "08001");
    }

    static void initialize() {
        if (initialized) {
            return;
        }
        initialized = true;
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }

    /* Prevent the DriverManager class from being instantiated. */
    private DriverManager(){}     
   
    private static java.util.Vector writeDrivers = new java.util.Vector();

    
    private static java.util.Vector readDrivers = new java.util.Vector();

    private static int loginTimeout = 0;
    private static java.io.PrintWriter logWriter = null;
    private static java.io.PrintStream logStream = null;
    private static boolean initialized = false;

    private static Object logSync = new Object();

    
    private static native ClassLoader getCallerClassLoader();

}

// DriverService is a package-private support class.    
class DriverService implements java.security.PrivilegedAction {
        Iterator ps = null;
	public DriverService() {};
        public Object run() {


	ps = Service.providers(java.sql.Driver.class);

	try {
           while (ps.hasNext()) {
               ps.next();
           } // end while
	} catch(Throwable t) {
	    // Do nothing
	}
        return null;
    } //end run

} 

// DriverInfo is a package-private support class.
class DriverInfo {
    Driver         driver;
    Class          driverClass;
    String         driverClassName;

    public String toString() {
	return ("driver[className=" + driverClassName + "," + driver + "]");
    }
}
相關文章
相關標籤/搜索