1 /**管理一个集合JDBC驱动的基础服务 2 注意:在新的JDBC2.0api中实现了新的DataSource接口,提供了另一种链接数据源的方式。 3 使用DataSource的对象是首选方案 4 */ 5 public class DriverManager { 6 7 // 注册了JDBC驱动的集合 8 private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); 9 10 /** 11 通过检查jdcb.properties加载初始化JDBC驱动 12 */ 13 static { 14 loadInitialDrivers(); 15 println("JDBC DriverManager initialized"); 16 } 17 18 /* 19 *对外使用提供数据库连接的方法, 20 *重点说明Reflection.getCallerClass()方法,该方法返回调用者的类 21 */ 22 @CallerSensitive 23 public static Connection getConnection(String url) 24 throws SQLException { 25 26 java.util.Properties info = new java.util.Properties(); 27 return (getConnection(url, info, Reflection.getCallerClass())); 28 } 29 30 // 用于根据url、对应的属性信息在registeredDrivers中找到合适的注册的驱动创建数据库链接 31 private static Connection getConnection( 32 String url, java.util.Properties info, Class<?> caller) throws SQLException { 33 /* 34 * When callerCl is null, we should check the application's 35 * (which is invoking this class indirectly) 36 * classloader, so that the JDBC driver class outside rt.jar 37 * can be loaded from here. 38 */ 39 ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; 40 synchronized(DriverManager.class) { 41 // synchronize loading of the correct classloader. 42 if (callerCL == null) { 43 callerCL = Thread.currentThread().getContextClassLoader(); 44 } 45 } 46 47 if(url == null) { 48 throw new SQLException("The url cannot be null", "08001"); 49 } 50 51 println("DriverManager.getConnection(\"" + url + "\")"); 52 53 // Walk through the loaded registeredDrivers attempting to make a connection. 54 // Remember the first exception that gets raised so we can reraise it. 55 SQLException reason = null; 56 57 for(DriverInfo aDriver : registeredDrivers) { 58 // If the caller does not have permission to load the driver then 59 // skip it. 60 //一个应用中有可能会有多个数据库驱动,需要判断数据库连接的调用者(调用getConnection()方法的对象)是否与驱动相匹配 61 if(isDriverAllowed(aDriver.driver, callerCL)) { 62 try { 63 println(" trying " + aDriver.driver.getClass().getName()); 64 Connection con = aDriver.driver.connect(url, info); 65 if (con != null) { 66 // Success! 67 println("getConnection returning " + aDriver.driver.getClass().getName()); 68 return (con); 69 } 70 } catch (SQLException ex) { 71 if (reason == null) { 72 reason = ex; 73 } 74 } 75 76 } else { 77 println(" skipping: " + aDriver.getClass().getName()); 78 } 79 80 } 81 82 // if we got here nobody could connect. 83 if (reason != null) { 84 println("getConnection failed: " + reason); 85 throw reason; 86 } 87 88 println("getConnection: no suitable driver found for "+ url); 89 throw new SQLException("No suitable driver found for "+ url, "08001"); 90 } 91 } 92 93 //一个应用中有可能会有多个数据库驱动,需要判断数据库连接的调用者(调用getConnection()方法的对象)是否与驱动相匹配 94 private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { 95 boolean result = false; 96 if(driver != null) { 97 Class<?> aClass = null; 98 try { 99 aClass = Class.forName(driver.getClass().getName(), true, classLoader); 100 } catch (Exception ex) { 101 result = false; 102 } 103 104 result = ( aClass == driver.getClass() ) ? true : false; 105 } 106 107 return result; 108 } 109 110 //根据URL从registeredDrivers 中获得驱动,根据Reflection.getCallerClass()返回的调用者类,在registeredDrivers 中进行匹配 111 @CallerSensitive 112 public static Driver getDriver(String url) 113 throws SQLException { 114 115 println("DriverManager.getDriver(\"" + url + "\")"); 116 117 Class<?> callerClass = Reflection.getCallerClass(); 118 119 // Walk through the loaded registeredDrivers attempting to locate someone 120 // who understands the given URL. 121 for (DriverInfo aDriver : registeredDrivers) { 122 // If the caller does not have permission to load the driver then 123 // skip it. 124 if(isDriverAllowed(aDriver.driver, callerClass)) { 125 try { 126 if(aDriver.driver.acceptsURL(url)) { 127 // Success! 128 println("getDriver returning " + aDriver.driver.getClass().getName()); 129 return (aDriver.driver); 130 } 131 132 } catch(SQLException sqe) { 133 // Drop through and try the next driver. 134 } 135 } else { 136 println(" skipping: " + aDriver.driver.getClass().getName()); 137 } 138 139 } 140 141 println("getDriver: no suitable driver"); 142 throw new SQLException("No suitable driver", "08001"); 143 } 144 145 146 /* 147 *注册数据驱动,使用同步方式,最终保存在CopyOnWriteArrayList的集合中 148 */ 149 public static synchronized void registerDriver(java.sql.Driver driver, 150 DriverAction da) 151 throws SQLException { 152 153 /* Register the driver if it has not already been added to our list */ 154 if(driver != null) { 155 registeredDrivers.addIfAbsent(new DriverInfo(driver, da)); 156 } else { 157 // This is for compatibility with the original DriverManager 158 throw new NullPointerException(); 159 } 160 161 println("registerDriver: " + driver); 162 163 }