以一段mysql jdbc加载的demo为例:
首先,
首先是获得了加载当前类的classloader,接下来将属性放入properties文件中,
接下来调用getConnection(url, info, callerCL)方法,这里面会调用initialize()->loadInitialDrivers();方法,loadInitialDrivers()方法中会首先尝试从System.getproperty中获取设置的jdbc.drivers属性,没设置就不管了,接下来会调用:
DriverService ds = new DriverService();
这个方法会调用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语句块:
,在这里,也向DriverManager注册了driver。
总的来说,所有数据库厂商提供的驱动都是要向DriverManger中registerDriver,这样才能在以后根据URL来判定调用哪个驱动器。而initialize-> loadInitialDrivers方法只是加载系统提供的驱动器,或者加载设置了jdbc.dirvers这个system.property的驱动,其他驱动的注册都是依赖于classloader的加载机制,通过static语句块来实现类的加载
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语句块来实现类的加载