日期:2014-05-16  浏览次数:20455 次

JDBC驱动加载过程
以一段mysql jdbc加载的demo为例:
  String url ="jdbc:mysql://localhost:3306/jdbcana";     
  String username = "root";
  String password = "root";
  Connection con = DriverManager.getConnection(url, username, password);


首先,
Connection con = DriverManager.getConnection(url, username, password)
  这段代码会得到connection,跟进代码,
public static Connection getConnection(String url, 
	String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();

        // Gets the classloader of the code that called this method, may 
	// be null.
	ClassLoader callerCL = DriverManager.getCallerClassLoader();

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

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


首先是获得了加载当前类的classloader,接下来将属性放入properties文件中,
接下来调用getConnection(url, info, callerCL)方法,这里面会调用initialize()->loadInitialDrivers();方法,loadInitialDrivers()方法中会首先尝试从System.getproperty中获取设置的jdbc.drivers属性,没设置就不管了,接下来会调用:
DriverService ds = new DriverService();
 // Have all the privileges to get all the 
	 // implementation of java.sql.Driver
	 java.security.AccessController.doPrivileged(ds);



这个方法会调用Service.providers(Driver.class);方法,他其实是从String str = "META-INF/services/" + this.service.getName();中加载类,这个类就是sun.jdbc.odbc.JdbcOdbcDriver,
return Class.forName(str, true, this.loader).newInstance();并生产实例,看sun.jdbc.odbc.JdbcOdbcDriver源码,它也是JdbcOdbcDriver localJdbcOdbcDriver = new JdbcOdbcDriver();然后DriverManager.registerDriver(localJdbcOdbcDriver);向驱动管理器注册了驱动,与Mysqljdbc一个道理,注册驱动代码中,会实例化DriverInfo,这是对驱动信息的封装,然后会向driver vetor中加入DriverInfo对象,初始化完成之后,从vetor中拿出DriverInfo,然后取出driver,调用connect方法,这个方法会解析url,如果符合当前驱动的规则,那么就用当前驱动,比如如果传入的是jdbc:mysql://localhost:3306/jdbcana就可以解析出来是用mysql jdbc 驱动。而Mysql jdbc驱动又是什么时候加载的呢,因为我们将mysql jar包加入了classpath环境下,所以systemclassloader会加载其环境下的jar包,而在Driver类中有一段static语句块:
try {
			java.sql.DriverManager.registerDriver(new Driver());
		} catch (SQLException E) {
			throw new RuntimeException("Can't register driver!");
		}
	}
static {
,在这里,也向DriverManager注册了driver。

总的来说,所有数据库厂商提供的驱动都是要向DriverManger中registerDriver,这样才能在以后根据URL来判定调用哪个驱动器。而initialize-> loadInitialDrivers方法只是加载系统提供的驱动器,或者加载设置了jdbc.dirvers这个system.property的驱动,其他驱动的注册都是依赖于classloader的加载机制,通过static语句块来实现类的加载