The role of class.forname in JDBC

  • 2020-04-01 02:51:48
  • OfStack

When using JDBC, it's natural to use the following statements:


Class.forName("com.mysql.jdbc.Driver");   
String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8";   
String user = "";   
String psw = "";   
Connection con = DriverManager.getConnection(url,user,psw);  

Why say very natural, because no matter be on the net or book tutorial the example is like this, and the program also did run normally, then everybody also feel at ease of looking for a gourd gourd to go down.
Does it have to be? No, we can replace it with the following sentence:


com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();   
//or :    
//new com.mysql.jdbc.Driver();  
String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8";   
String user = "";   
String psw = "";   
Connection con = DriverManager.getConnection(url,user,psw); 

As you can probably see, we just need to make sure that the corresponding Driver class is loaded into the JVM and the class initialization is done before we call DriverManager's getConnection method. Both of the above methods can achieve this function, so the program can work properly. Note that the program will not work properly if we do the following, because this simply loads the Driver class into the JVM without any initialization.


com.mysql.jdbc.Driver driver = null;   
//or :    
ClassLoader cl = new ClassLoader();   
cl.loadClass("com.mysql.jdbc.Driver");  

We all know that JDBC is designed using the Bridge pattern, with DriverManager as the Driver, java.sql.Driver as the Implementor, and com.mysql.jdbc.Driver as a concrete implementation of Implementor (see the Bridge pattern description for GOF). Notice that the previous Driver is an interface and the latter is a class that implements the previous Driver interface.
In the Bridge pattern, DriverManager is supposed to have a reference to Implementor (Driver), but we didn't register the Driver object with DriverManager during the implementation. What happened? The JDK documentation describes Driver in this way:
When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager
Well, it turned out that com.mysql.jdbc.driver automatically completed this step for us after loading. The source code looks like this:


package com.mysql.jdbc   

public class Driver extends NonRegisteringDriver implements java.sql.Driver {   
 // ~ Static fields/initializers  
 // Register ourselves with the DriverManager  
 //  
 static {   
    t ry {   
              java.sql.DriverManager.registerDriver(new Driver());   
          } catch (SQLException E) {   
              throw new RuntimeException("Can't register driver!");   
          }   
  }   
// ~ Constructors  
  
 public Driver() throws SQLException {   
     // Required for Class.forName().newInstance()  
 }   
} 

PS: fix JDBC driver loading


ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = cl.loadClass("com.mysql.jdbc.Driver");
clazz.newInstance();
Connection conn = DriverManager.getConnection("jdbcurl");

It can also be executed. But this creates an extra instance of com.mysql.jdbc.driver. With the Class. Class.forname (". Com. Mysql. JDBC Driver ").

That is:


Class.forName("com.mysql.jdbc.Driver")==cl.loadClass("com.mysql.jdbc.Driver").newInstance();

Class.forname and classloader.loadclass are two different things, an instantiated Class and a loaded Class


Related articles: