JDBC driver initialization-Mysql

JDBC driver initialization-Mysql: http://donald-draper.iteye.com/blog/2342010
JDBC connection acquisition: http://donald-draper.iteye.com/blog/2342011
Mysql load balancing connection acquisition: http: //donald-draper.iteye.com/blog/2342089
Mysql master-slave replication read-write separation connection acquisition: http://donald-draper.iteye.com/blog/2342108
ConnectionImp creates MysqlIO: http://donald-draper .iteye.com/blog/2342959
Mysql precompiled SQL: http://donald-draper.iteye.com/blog/2342960
MysqlSQL PreparedStatement Query: http://donald-draper.iteye.com/blog/2343083
MySQL ServerPreparedStatement Query: http://donald-draper.iteye.com/blog/2343124
When using hibernate and mybatis as the persistence layer, shield the jdbc stuff. Now that we have time, let's take a look at the underlying jdbc stuff.
First create a mysql test instance as follows;
test instance:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;
public class testMysqlX {
	public static void main(String[] args){
		testMysqlConnection();
	}
	@SuppressWarnings("deprecation")
	public static void testMysqlConnection()
	{
	    Connection con = null;// Create a database connection
	    PreparedStatement pre = null;// Create a precompiled statement object, generally use this instead of Statement
	    ResultSet result = null;// Create a result set object
	    try
	    {
	        Class.forName("com.mysql.jdbc.Driver");// Load the driver
	        System.out.println("Start trying to connect to the database!");
	        String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8";
			String user = "root";//User name, the system default account name
			String password = "123456";//The password you set during installation	
	        long startTime = System.currentTimeMillis();
	        con = DriverManager.getConnection(url, user, password);// Get the connection
	        PreparedStatement ps = con.prepareStatement("select count(*) from ?");
	        ps.setString(1, "user");
	        result = ps.executeQuery();
	        //result The initial cursor is head, move next to the first record
	          while(result.next()){
		         int sum = result.getInt(1);
	        	 System.out.println("============sum:"+sum);
	         }
	        long endTime = System.currentTimeMillis();
	 
	        System.out.println("============time:"+ (endTime-startTime));
	        System.out.println("============hashCode:"+ con.hashCode());
	        if(!con.isClosed()){
	        	 System.out.println("============Connection succeeded!");
	        }
	    }
	    catch (Exception e)
	    {
	    	System.out.println("============Connection failed: "+e.getMessage());
	    	e.printStackTrace ();
	    }
	    finally
	    {
	        try
	        {
	            // Close the above objects one by one, because not closing them will affect performance and occupy resources
	            // Note the order of closing, the last used closes first
	            if (result != null)
	                result.close();
	            if (pre != null)
	                pre.close();
	            if (con != null)
	                con.close();
	            System.out.println("Database connection closed!");  
	        }
	        catch (Exception e)
	        {
	            e.printStackTrace ();
	        }
	    }
	}
}


Let's take a look at the whole process of loading from the driver, getting the connection, getting the PreparedStatement, executing the query, and processing the result set; let's look at the
loading driver and start with
this sentence:
Class.forName("com.mysql.jdbc.Driver");

//Class
public final
    class Class<T> implements java.io.Serializable,
			      java.lang.reflect.GenericDeclaration,
			      java.lang.reflect.Type,
                              java.lang.reflect.AnnotatedElement {
    private static final int ANNOTATION= 0x00002000;
    private static final int ENUM      = 0x00004000;
    private static final int SYNTHETIC = 0x00001000;

    private static native void registerNatives();
    static {
        registerNatives();
    }
//Load the corresponding class according to the class name
   public static Class<?> forName(String className)
                throws ClassNotFoundException {
        return forName0(className, true, ClassLoader.getCallerClassLoader());
    }
 /** Called after security checks have been made. */
    private static native Class forName0(String name, boolean initialize,
					    ClassLoader loader)
	throws ClassNotFoundException;
}

Take a look at the Driver class of mysql
//com.mysql.jdbc.Driver 
public class Driver extends NonRegisteringDriver
    implements java.sql.Driver
{
    public Driver()
        throws SQLException
    {
    }
    static
    {
        try
        {
	    //Register the driver to the driver manager
            DriverManager.registerDriver(new Driver());
        }
        catch(SQLException E)
        {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

//DriverManager
public class DriverManager {
    /* write copy of the drivers vector */
    private static java.util.Vector writeDrivers = new java.util.Vector();

    /* write copy of the drivers vector */
    private static java.util.Vector readDrivers = new java.util.Vector();

    private static int loginTimeout = 0;
    private static java.io.PrintWriter logWriter = null;
    private static java.io.PrintStream logStream = null;
    private static boolean initialized = false;
        //register the driver
	public static synchronized void registerDriver(java.sql.Driver driver)
	throws SQLException {
	if (!initialized) {
	    initialize();
	}
        //Initialize driver information
	DriverInfo in = new DriverInfo();

	di.driver = driver;
	di.driverClass = driver.getClass();
	di.driverClassName = di.driverClass.getName ();

        //Add driver information to the writeDrivers collection
	writeDrivers.addElement(di);
	println("registerDriver: " + di);
	//Clone writeDrivers to readDrivers
	readDrivers = (java.util.Vector) writeDrivers.clone();

    }
     //initialization
    static void initialize() {
        if (initialized) {
            return;
        }
        initialized = true;
	//Load driver, initialize
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }
    //load driver
     private static void loadInitialDrivers() {
        String drivers;
        try {
	    drivers = (String) java.security.AccessController.doPrivileged(
		new sun.security.action.GetPropertyAction("jdbc.drivers"));
        } catch (Exception ex) {
            drivers = null;
        }
	//If the driver is placed in a jar package and loaded through the type loader, all Drivers, each java.sql.Driver.class is a Service
	 DriverService ds = new DriverService();

	 //Get access to all drivers
	 java.security.AccessController.doPrivileged(ds);		
	        
         println("DriverManager.initialize: jdbc.drivers = " + drivers);
        if (drivers == null) {
            return;
        }
        while (drivers.length() != 0) {
            int x = drivers.indexOf(':');
            String driver;
            if (x < 0) {
                driver = drivers;
                drivers = "";
            } else {
                driver = drivers.substring(0, x);
                drivers = drivers.substring(x+1);
            }
            if (driver.length() == 0) {
                continue;
            }
            try {
                println("DriverManager.Initialize: loading " + driver);
		//load driver
                Class.forName(driver, true,
			      ClassLoader.getSystemClassLoader());
            } catch (Exception ex) {
                println("DriverManager.Initialize: load failed: " + ex);
            }
        }
    }
    class DriverService implements java.security.PrivilegedAction {
        Iterator ps = null;
	public DriverService() {};
        public Object run() {

	// uncomment the followin line before mustang integration 	
        // Service s = Service.lookup(java.sql.Driver.class);
	// ps = s.iterator();
        //Load all Drivers through Service
	ps = Service.providers(java.sql.Driver.class);

	/* 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 sun.misc.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 (ps.hasNext()) {
	       //Initialize Driver
               ps.next();
           } // end while
	} catch(Throwable t) {
	    // Do nothing
	}
        return null;
    } //end run

} //end DriverService
    //Driver information class
    class DriverInfo {
    Driver         driver;
    Class          driverClass;
    String         driverClassName;

    public String toString() {
	return ("driver[className=" + driverClassName + "," + driver + "]");
    }
}

It can be seen from the initialization process of DriverManager that the loading of Driver is delegated to DriverService, and DriverService is
loaded through Service. Let's take a look at Service
public final class Service
{
    //Load the driver and delegate to providers(Class class1, ClassLoader classloader)
    public static Iterator providers(Class class1)
        throws ServiceConfigurationError
    {
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        return providers(class1, classloader);
    }
    public static Iterator providers(Class class1, ClassLoader classloader)
        throws ServiceConfigurationError
    {
         //Actually returned is an Iterator, LazyIterator is the static inner class of Service
        return new LazyIterator(class1, classloader);
    }
    //LazyIterator, lazy loading driver collection
    private static class LazyIterator
        implements Iterator
    {

        public boolean hasNext()
            throws ServiceConfigurationError
        {
            if(nextName != null)
                return true;
            if(configs == null)
                try
                {
                    String s = (new StringBuilder()).append("META-INF/services/").append(service.getName()).toString();
                    if(loader == null)
                        configs = ClassLoader.getSystemResources(s);
                    else
                        configs = loader.getResources(s);
                }
                catch(IOException ioexception)
                {
                    Service.fail(service, (new StringBuilder()).append(": ").append(ioexception).toString());
                }
            for(; pending == null || !pending.hasNext(); pending = Service.parse(service, (URL)configs.nextElement(), returned))
                if(!configs.hasMoreElements())
                    return false;

            nextName = (String)pending.next();
            return true;
        }
        //The next function is called in DriverService, and loads the driver by traversing the LazyIterator
        public Object next()
            throws ServiceConfigurationError
        {
            String s;
            Class class1;
            if(!hasNext())
                throw new NoSuchElementException();
            s = nextName;
            nextName = null;
            class1 = null;
            try
            {
                class1 = Class.forName(s, false, loader);
            }
            catch(ClassNotFoundException classnotfoundexception)
            {
                Service.fail(service, (new StringBuilder()).append("Provider ").append(s).append(" not found").toString());
            }
            if(!service.isAssignableFrom(class1))
                Service.fail(service, (new StringBuilder()).append("Provider ").append(s).append(" not a subtype").toString());
            return service.cast(class1.newInstance());
            Throwable throwable;
            throwable;
            Service.fail(service, (new StringBuilder()).append("Provider ").append(s).append(" could not be instantiated: ").append(throwable).toString(), throwable);
            return null;
        }

        public void remove()
        {
            throw new UnsupportedOperationException();
        }

        Class service;
        ClassLoader loader;
        Enumeration configs;
        Iterator pending;
        Set returned;
        String nextName;

        private LazyIterator(Class class1, ClassLoader classloader)
        {
            configs = null;
            pending = null;
            returned = new TreeSet();
            nextName = null;
            service = class1;
            loader = classloader;
        }
	
    private static void fail(Class class1, String s, Throwable throwable)
        throws ServiceConfigurationError
    {
        ServiceConfigurationError serviceconfigurationerror = new ServiceConfigurationError((new StringBuilder()).append(class1.getName()).append(": ").append(s).toString());
        serviceconfigurationerror.initCause(throwable);
        throw serviceconfigurationerror;
    }
    //Processing of driver loading failure, throwing an exception
    private static void fail(Class class1, String s)
        throws ServiceConfigurationError
    {
        throw new ServiceConfigurationError((new StringBuilder()).append(class1.getName()).append(": ").append(s).toString());
    }

    private static void fail(Class class1, URL url, int i, String s)
        throws ServiceConfigurationError
    {
        fail(class1, (new StringBuilder()).append(url).append(":").append(i).append(": ").append(s).toString());
    }
}

//ServiceConfigurationError
public class ServiceConfigurationError extends Error
{
    public ServiceConfigurationError(String s)
    {
        super(s);
    }
    public ServiceConfigurationError(Throwable throwable)
    {
        super(throwable);
    }
}

At this point, the loading of the driver is over. Let's review the whole process. The Class loads com.mysql.jdbc.Driver, and com.mysql.jdbc.Driver registers the Driver to the DriverManager through the static statement block. The DriverManager first checks whether it is initialized or not. Then load the driver class. The entire driver loading process is through the
DriverService , and the DriverService is delegated to the Service. The Service loads the driver and returns all the Iterators implemented by java.sql.Driver. The Iterator is LazyIterator. Drive; finally wrap the Driver into DriverInfo, add it to the writeDrivers collection, and clone it to readDrivers.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326475101&siteId=291194637