1 /**管理一个集合JDBC驱动的基础服务 2 注意:在新的JDBC2.0api中实现了新的DataSource接口,提供了另一种链接数据源的方式。 3 使用DataSource的对象是首选方案 4 */ 5 public class DriverManager { 6 7 // 注册了JDBC驱动的集合 8 private final static CopyOnWriteArrayListregisteredDrivers = 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 @CallerSensitive112 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 someone120 // who understands the given URL.121 for (DriverInfo aDriver : registeredDrivers) {122 // If the caller does not have permission to load the driver then123 // 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 DriverManager158 throw new NullPointerException();159 }160 161 println("registerDriver: " + driver);162 163 }