JDBC 驱动加载注册过程分析

以MySQL数据库提供的驱动com.mysql.jdbc.Driver为例:

一、Driver接口

1、首先我们看一下JDBC标准定义的Driver接口:
    

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所定义标准的实现。

2、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");

时,会执行上面的静态代码块,从而加载注册我们提供的数据库驱动。

二、DriverManager驱动管理器

DriverManager类是整个JDBC的起点!利用它可以加载并注册我们的驱动,创建连接,从而完成后续的操作。

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

转载于:https://my.oschina.net/xiaomaoandhong/blog/60810

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值