Analysis of the driver loading process in JDBC (I)

Source: Internet
Author: User
Tags driver manager

From: http://miaoxiaodong78.blog.163.com/blog/static/1876513620061161412821/

This article starts from Java. SQL. driver Interface, Java. SQL. the drivemanager class and other open source database driver classes discuss the entire process of driver loading in JDBC and how the JDBC framework implements "pluggable" details.

This article contains many parts. For example, classloaders, local methods, Object locks, class locks, feature-based or status-based separation locks, and security mechanisms are not discussed in depth! You can continue to follow this blog for details! In my previous article, I mainly focused on the initialization of the driver manager, connection establishment, driver registration, driver columns, driver cancellation registration, and log operations in drivermanager.

I. Driver Interface
// Driver. javapackage Java. SQL; public interface driver {connection connect (string URL, Java. util. properties info) throws sqlexception; Boolean acceptsurl (string URL) throws sqlexception; driverpropertyinfo [] getpropertyinfo (string URL, Java. util. properties info) throws sqlexception; int getmajorversion (); // return the driver's main version int getminorversion (); // return the driver's minor version Boolean jdbccompliant (); // compatible with JDBC standards}

The above is the driver interface in JDBC. It is an interface that must be implemented by the driver class of any database provider. The driver class must implement all the methods in this interface! Easy!

The reason why it is an interface is the specific application of "dip-dependence inverse principle", which is often mentioned in OO! In the drivermanager class, we can see that all the drivers used are driver interfaces, which depend on the upper layer and do not rely on implementation. In this way, you can use JDBC
Framework manages and maintains the database drivers of different JDBC providers.

The driver of multiple databases can be loaded in the JDBC framework! Correspondingly, it is generally recommended that the driver of the database provider be smaller, so that it will not occupy too much memory after loading multiple drivers.

There are six methods in the driver interface. The Red Two are relatively important. They are called by drivermanager. The other four are simple methods! The following describes the meaning of the first two methods!

Connection connect (string URL, Java. util. properties info) throws sqlexception is a required method for the driver of the database provider. It primarily uses the specified URL and information related to the specific provider to establish a connection.

The Boolean acceptsurl (string URL) throws sqlexception method is also required by the driver of the database provider. It mainly determines whether a driver introduces the URL. (Usually called before a connection is established. Drivermanager class)

2. drivermanager class

The drivermanager class is the starting point of the entire JDBC! You can create a connection to complete subsequent operations. In JDBC, drivermanager is a relatively complex class, so we can only be divided into several categories. In this article, the drivermanager methods are divided into three categories: 1. Initialization; 2. Driver registration, query, and cancellation; 3. Connection establishment; 4. Log-related.

 

Let's take a look at its source code!

//DriverManager.java        1.45 05/11/17package java.sql;import sun.misc.Service;import java.util.Iterator;class DriverInfo {    Driver         driver;    Class          driverClass;    String         driverClassName;    public String toString() {     return ("driver[className=" + driverClassName + "," + driver + "]");    }}public class DriverManager {    // Prevent the DriverManager class from being instantiated.    private DriverManager(){}

The above is the front part of the code. It mainly involves the definition of packages, the import of related files, the definition of classes, and a private constructor-that is, this class cannot be instantiated and can only call its static method, it is equivalent to a tool Class-A management-driven tool class! Another is the auxiliary class driverinfo, which encapsulates the driver class and contains the name of the driver class and the driver class.

Next, let's start to introduce the drivermanager class's important methods!

1. Initialization
Private Static Java. util. vector drivers = new Java. util. vector (); // Save the aggregation Private Static Boolean initialized = false of multiple drivers; // whether to initialize the flag, whether the initialization method is static void initialize () {If (initialized) {return;} // is returned after initialization! (Initialize) initialized = true; // sets this identifier, indicating that the initialization has been completed loadinitialdrivers (); // Initialization is mainly to complete the loading of all drivers println ("JDBC drivermanager initialized ");} // complete the loading of all drivers provided by the system in the initialization method. Private Static void loadinitialdrivers () {string drivers; try {drivers = (string) Java. security. accesscontroller. doprivileged (new sun. security. action. getpropertyaction ("JDBC. drivers "); // obtain the system property" JDBC. the driver name corresponding to drivers !).} Catch (exception ex) {drivers = NULL;} iterator PS = service. providers (Java. SQL. driver. class); // load the drive while (PS. hasnext () {// load these drivers to instantiate them ps. next ();} println ("drivermanager. initialize: JDBC. drivers = "+ drivers); If (drivers = NULL) {return;} // if the driver is not specified for the system attribute, the while (drivers. length ()! = 0) {// The loop process. For more information, see 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); Class. forname (driver, true, classloader. getsystemclassloader (); // load these drivers. The details will be explained in the next article.} catch (exception ex) {PR Intln ("drivermanager. initialize: Load failed: "+ ex) ;}// end of while // system attribute" JDBC. drivers may have multiple database drivers whose names are separated by ":". // the above process is the driver separated, repeat the column in sequence, and then call class. forname loading in turn} private static object logsync = new object (); // object lock // below is an auxiliary method for writing information to the log! Public static void println (string message) {synchronized (logsync) {// an important method for consistent programming. For details, see if (logwriter! = NULL) {// set the log to write the following information: logwriter. println (Message); // write information to logger: logwriter. Flush ();}}}

// The above blue attributes and methods are important methods in concurent programming.

// First, we can call other non-log writing methods when writing information to logs,

// Different customers cannot call the write method at the same time-one customer is writing data, and others must wait for writing.

// If we use synchronized (this) or synchronized mechanically, this write method will inevitably lead to low efficiency

// Generally, when multiple methods in a class can be divided into multiple different groups and the methods in these groups do not interfere with each other,

// You can specify a lock for each group to restrict the use of the same method by multiple customers, so as to ensure that

// Consistency to ensure unnecessary synchronized methods!

// For consistent programming, please pay more attention to the articles in the blog

 

2. Driver registration, query, and cancellation
// Register the specified driver with drivermanager. Please read the next article for driver registration! Public static synchronized void registerdriver (Java. SQL. driver Driver) throws sqlexception {If (! Initialized) {initialize () ;}// before registration, you must initialize driverinfo di = new driverinfo (); // create a new driver information class di. driver = driver; Di. driverclass = driver. getclass (); Di. driverclassname = di. driverclass. getname (); // enter the registration driver information drivers. addelement (DI); // if the driver information is println ("registerdriver:" + DI);} public static synchronized driver getdriver (string URL) in the driver Aggregation) throws sqlexception {println ("drivermanager. getdriver ("" + URL + "") "); If (! Initialized) {initialize ();} // you must first initialize the // local method to obtain the classloader callercl = drivermanager that calls this method. getcallerclassloader (); // all the driver information in the column and return the driver for (INT I = 0; I <drivers. size (); I ++) {// aggregate driverinfo di = (driverinfo) drivers of the drive information in the column. elementat (I); // If (getcallerclass (callercl, Di. driverclassname )! = Di. driverclass) {println ("Skipping:" + DI); continue;} Try {println ("trying" + DI); If (Di. driver. acceptsurl (URL) {// when the driver understands this URL, the returned driver println ("getdriver returning" + DI); Return (Di. driver) ;}} catch (sqlexception ex) {// drop through and try the next driver .}} println ("getdriver: no suitable driver"); throw new sqlexception ("no suitable driver", "08001");} // unregister a certain Driver. The applet can only cancel registration of the public static synchronized void deregisterdriver (driver Driver) throws sqlexception {classloader callercl = drivermanager loaded from its class loader. getcallerclassloader (); println ("drivermanager. deregisterdriver: "+ driver); int I; driverinfo di = NULL; for (I = 0; I <drivers. size (); I ++) {di = (driverinfo) drivers. elementat (I); If (Di. driver = driver) {break;} // if a driver is found, return an I value.} if (I> = Drivers. size () {// after all the columns are completed, if no driver is found, println ("couldn't find driver to unload"); Return ;}// find this driver, however, if the caller cannot load the driver, an exception if (getcallerclass (callercl, Di. driverclassname )! = Di. driverclass) {Throw new securityexception ();} // after all the preceding operations, you can delete the drivers driver. removeelementat (I);} // obtain the enumeration of all currently loaded JDBC drivers ** public static synchronized Java. util. enumeration getdrivers () {Java. util. vector result = new Java. util. vector (); If (! Initialized) {initialize ();} // initialization must be completed when the class is not initialized. // For details, see the initialization section classloader callercl = drivermanager. getcallerclassloader (); // get the class loader of the current class for (INT I = 0; I <drivers. size (); I ++) {// all driver driverinfo di = (driverinfo) drivers. elementat (I); // get a specific driver // If the caller is not allowed to load the driver, ignore the driver if (getcallerclass (callercl, Di. driverclassname )! = Di. driverclass) {println ("Skipping:" + DI); continue;} result. addelement (Di. driver); // Add the loaded driver to the result set to be returned} return (result. elements (); // returned result set} Private Static native classloader getcallerclassloader (); // obtain the local method of the Class Loader of the current caller (for the local method JNI, please follow this blog post) // return the class object. We use the local method getcallerclassloader () of drivermanager to obtain the caller's class loader Private Static class getcallerclass (classloader callerclassloader, string driverclassname) {// callerclassloader is the class loader, driverclassname is the name of the driver class callerc = NULL; try {callerc = Class. forname (driverclassname, true, callerclassloader); // use the specified classloader to locate and load the specified Driver Class, // true indicates that the driver class will be initialized when it is not initialized. Return this class} catch (exception ex) {callerc = NULL; // being very careful} return callerc;
3. Establish a connection

In JDBC, The drivermanager. getconnection method is generally used to return a connection. This method has multiple variants, all of which use the Connect Method of the specific driver class to implement the connection. The following describes the core connection methods.

Private Static connection getconnection (string URL, Java. util. properties info, classloader callercl) throws sqlexception {// when the class loader is null, you must check the class loader of the application // others in RT. JDBC driver classes other than jar can be loaded from the driver/* synchronized (drivermanager. class) {// synchronize the current drivermanger class if (callercl = NULL) {callercl = thread. currentthread (). getcontextclassloader ();} // get the class loader of the current thread (for the true meaning of this sentence, follow the thread-related articles)} If (url = NULL) {Throw new sqlexception ("The URL cannot be null", "08001");} println ("drivermanager. getconnection (" "+ URL +") "); If (! Initialized) {initialize () ;}// Initialization is required. Add the default driver to all the current drivers in the // column and try to establish a connection to sqlexception reason = NULL; for (INT I = 0; I <drivers. size (); I ++) {driverinfo di = (driverinfo) drivers. elementat (I); // If the caller is not allowed to load the class, ignore it if (getcallerclass (callercl, Di. driverclassname )! = Di. driverclass) {// when the driver is not loaded by the class loader of the current caller, ignore this driver println ("Skipping:" + DI); continue ;} try {println ("trying" + DI); connection result = di. driver. connect (URL, Info); // call the connection method of a driver to establish a connection if (result! = NULL) {// print the connection information after the connection is established and return the connection println ("getconnection returning" + DI); Return (result) ;}} catch (sqlexception ex) {If (reason = NULL) {reason = ex;} // The first error Oh} // the above process either returns a connection or throws an exception, when an exception is thrown, the cause of the exception is displayed, that is, assigning a value to the reason. // if an error occurs and the exception is thrown if (reason! = NULL) {println ("getconnection failed:" + reason); throw reason;} // if no connection is returned, there is no exception. Otherwise, no proper connection is printed, println ("getconnection: no suitable driver"); throw new sqlexception ("no suitable driver", "08001 ");} // The following three methods are variants of the above connection method, and the above connection method public static connection getconnection (string URL, Java. util. properties info) throws sqlexception {classloader callercl = drivermanager. getcallerclassloader ();// If there is no classloader, It is the caller's classloader return (getconnection (URL, info, callercl);} public static connection getconnection (string URL, string user, string password) throws sqlexception {Java. util. properties info = new Java. util. properties (); classloader callercl = drivermanager. getcallerclassloader (); If (user! = NULL) {info. Put ("user", user) ;}if (password! = NULL) {info. put ("password", password);} return (getconnection (URL, info, callercl);} public static connection getconnection (string URL) throws sqlexception {Java. util. properties info = new Java. util. properties (); classloader callercl = drivermanager. getcallerclassloader (); Return (getconnection (URL, info, callercl ));}
4. Log-related

There are several log-related methods in drivermanager, mainly divided into Stream-related methods that have been deprecated, and recommended reader and writer methods. (Corresponding to Java
Io compaction stream and word throttling! Because the information written to the log is generally the byte stream, the method related to the byte stream is discarded)

// Constant. Allow Logging stream final static sqlpermission set_log_permission = new sqlpermission ("setlog"); Private Static int logintimeout = 0; Private Static Java. io. printwriter logwriter = NULL; // write the volume stream Private Static Java. io. printstream logstream = NULL; // The written byte stream // sets the maximum time that the driver will wait for when trying to connect (log) public static void setlogintimeout (INT seconds) {logintimeout = seconds ;} public static int getlogintimeout () {retur N (logintimeout);} public static Java. io. printwriter getlogwriter () {// get logwriter return logwriter;} public static void setlogwriter (Java. io. printwriter out) {// sets the producer stream securitymanager sec = system. getsecuritymanager (); // obtain the security manager if (sec! = NULL) {SEC. checkpermission (set_log_permission);} // check whether you have the permission to write logs. If you have the permission, continue. Otherwise, an exception is thrown! Logstream = NULL; logwriter = out;} public static void setlogstream (Java. Io. printstream out) {// set the byte stream securitymanager sec = system. getsecuritymanager (); If (sec! = NULL) {SEC. checkpermission (set_log_permission);} logstream = out; If (OUT! = NULL) logwriter = new Java. io. printwriter (out); // wrap the byte stream as else logwriter = NULL;} public static Java. io. printstream getlogstream () {// get the byte stream return logstream ;}}

The above corresponds to the drivermanager. getconnection () method that teaches you how to build a simple JDBC program.

In the next article, we will focus on how database providers register their own drivers, that is, the class. forname () method. And "pluggable" concepts!


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.