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 }
