/** * 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"); } }); } 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() {
/* Load these drivers, so that they can be instantiated. * It may be the case that the driver class may not be there * i.e. there may be a packaged driver with the service class * as implementation of java.sql.Driver but the actual class * may be missing. In that case a java.util.ServiceConfigurationError * will be thrown at runtime by the VM trying to locate * and load the service. * * Adding a try catch block to catch those runtime errors * if driver not available in classpath but it's * packaged as service and that service is there in classpath. */ try{ while(driversIterator.hasNext()) { driversIterator.next(); } } catch(Throwable t) { // Do nothing } returnnull; } }); println("DriverManager.initialize: jdbc.drivers = " + drivers);
/** * Registers the given driver with the {@code DriverManager}. * A newly-loaded driver class should call * the method {@code registerDriver} to make itself * known to the {@code DriverManager}. If the driver is currently * registered, no action is taken. * * @param driver the new JDBC Driver that is to be registered with the * {@code DriverManager} * @param da the {@code DriverAction} implementation to be used when * {@code DriverManager#deregisterDriver} is called * @exception SQLException if a database access error occurs * @exception NullPointerException if {@code driver} is null * @since 1.8 */ publicstaticsynchronizedvoidregisterDriver(java.sql.Driver driver, DriverAction da) throws SQLException {
/* Register the driver if it has not already been added to our list */ if(driver != null) { registeredDrivers.addIfAbsent(newDriverInfo(driver, da)); } else { // This is for compatibility with the original DriverManager thrownewNullPointerException(); }
println("registerDriver: " + driver);
}
将自己注册到驱动管理器的驱动列表中
1 2 3 4 5 6
publicclassDriverManager {
// List of registered JDBC drivers privatefinalstatic CopyOnWriteArrayList<DriverInfo> registeredDrivers = newCopyOnWriteArrayList<>();
privatestatic Connection getConnection( String url, java.util.Properties info, Class<?> caller)throws SQLException { /* * When callerCl is null, we should check the application's * (which is invoking this class indirectly) * classloader, so that the JDBC driver class outside rt.jar * can be loaded from here. */ ClassLoadercallerCL= caller != null ? caller.getClassLoader() : null; synchronized(DriverManager.class) { // synchronize loading of the correct classloader. if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } }
// Walk through the loaded registeredDrivers attempting to make a connection. // Remember the first exception that gets raised so we can reraise it. SQLExceptionreason=null;
for(DriverInfo aDriver : registeredDrivers) { // If the caller does not have permission to load the driver then // skip it. if(isDriverAllowed(aDriver.driver, callerCL)) { try { println(" trying " + aDriver.driver.getClass().getName()); Connectioncon= 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; } }