static{try{
DriverManager.registerDriver(newDriver());//执行Driver中的静态代码块}catch(SQLException var1){thrownewRuntimeException("Can't register driver!");}}//进入registerDriver方法之前,也会调用DriverManager中的静态代码块/**
* Load the initial JDBC drivers by checking the System property
* jdbc.properties and then use the {@code ServiceLoader} mechanism
*/static{loadInitialDrivers();//主要看这个方法println("JDBC DriverManager initialized");}privatestaticvoidloadInitialDrivers(){
String drivers;try{
drivers = AccessController.doPrivileged(newPrivilegedAction<String>(){public String run(){return System.getProperty("jdbc.drivers");//首先这种方式的加载为 null}});}catch(Exception ex){
drivers = null;}// If the driver is packaged as a Service Provider, load it.// Get all the drivers through the classloader// exposed as a java.sql.Driver.class service.// ServiceLoader.load() replaces the sun.misc.Providers()
AccessController.doPrivileged(newPrivilegedAction<Void>(){public Void run(){
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);//★★★★
Iterator<Driver> driversIterator = loadedDrivers.iterator();try{while(driversIterator.hasNext()){
driversIterator.next();}}catch(Throwable t){// Do nothing}return null;}});println("DriverManager.initialize: jdbc.drivers = "+ drivers);if(drivers == null || drivers.equals("")){return;}
String[] driversList = drivers.split(":");//这里获取到有几种 驱动类型println("number of Drivers:"+ driversList.length);for(String aDriver : driversList){try{println("DriverManager.Initialize: loading "+ aDriver);//这里通过系统类加载器加载驱动,并初始化
Class.forName(aDriver,true, ClassLoader.getSystemClassLoader());}catch(Exception ex){println("DriverManager.Initialize: load failed: "+ ex);}}}
进入到DriverManager类中的getConnection():
/**
Attempts to establish a connection to the given database URL. The DriverManager attempts to
select an appropriate driver from the set of registered JDBC drivers.
*/publicstatic Connection getConnection(String url, String user, String password)throws SQLException {
java.util.Properties info =newjava.util.Properties();if(user != null){
info.put("user", user);}if(password != null){
info.put("password", password);}//Reflection.getCallerClass()这个方法是得到 调用该方法的类 的class对象。return(getConnection(url, info, Reflection.getCallerClass()));}//进入getConnection方法privatestatic Connection getConnection(
String url, java.util.Properties info, Class<?> caller)throws SQLException {//得到调用该方法的类 的class对象的类加载器 这里class对象是MyTest27,加载它的加载器是 系统类加载器。
ClassLoader callerCL = caller != null ? caller.getClassLoader(): null;synchronized(DriverManager.class){// synchronize loading of the correct classloader.if(callerCL == null){
callerCL = Thread.currentThread().getContextClassLoader();}}if(url == null){thrownewSQLException("The url cannot be null","08001");}println("DriverManager.getConnection(\""+ url +"\")");// Walk through the loaded registeredDrivers attempting to make a connection.// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;//这里将会遍历registeredDrivers,registeredDrivers存放了到底有几个可用驱动,然后从中找到合适的驱动for(DriverInfo aDriver : registeredDrivers){// If the caller does not have permission to load the driver then// skip it.//★ 这里为真的时候,才会真正的执行try里面的代码if(isDriverAllowed(aDriver.driver, callerCL)){try{println(" trying "+ aDriver.driver.getClass().getName());//进而获取数据库连接,通过connect方法获取,见下面的图
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;}println("getConnection: no suitable driver found for "+ url);thrownewSQLException("No suitable driver found for "+ url,"08001");}//进入isDriverAllowed方法,找个合适的驱动,并使用 classLoader(还是上面加载MyTest27的加载器:系统类加载器)privatestaticbooleanisDriverAllowed(Driver driver, ClassLoader classLoader){boolean result =false;if(driver != null){
Class<?> aClass = null;try{//★使用系统类加载器加载相应的驱动,并初始化 true . 这里的加载不是主要目的,目的是下面的★
aClass = Class.forName(driver.getClass().getName(),true, classLoader);}catch(Exception ex){
result =false;}//★ 就是为了避免类加载的时候的命名空间问题。//之前 driver已经被加载过了, 之前的加载和现在的要做的加载必须是用一个类加载器去加载
result =( aClass == driver.getClass())?true:false;}return result;}