您当前的位置:学院动态 > 校区新闻 > 正文

Class.forName("com.mysql.jdbc.Driver")的应用

  
时间:2017-09-06 16:40    来源:顽石科技    编辑:www.zrzxtime.com
 
  在使用传统的JDBC连接数据库的时候,总是需要这一句(以MySQL为例):
  
  Class.forName("com.mysql.jdbc.Driver");   
  
  只是看网上的例子都这么写,于是便懒得去管内部原理。不过大概还是清楚的,知道这句话是向DriverManage注册了一个MySQL的JDBC Driver。
 
为什么
 
  
  但为什么要用Class.forName呢?
  
  网上还流传了一个这样的版本:Class.forName("com.mysql.jdbc.Driver").newInstance()。
  
  经过实验,发现用com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver() 也是可以的,但是只声明com.mysql.jdbc.Driver driver = null ,而不实例化却又是不行的。
  
  那么Driver的注册到底是在类的初始化时进行的,还是在类的对象初始化时进行的呢?我也不知道,最好的办法还是看源码: 
  
  package com.mysql.jdbc;
  
  import Java.sql.DriverManager;
  
  import java.sql.SQLException;
  
  // Referenced classes of package com.mysql.jdbc:
  
  // NonRegisteringDriver
  
  public class Driver extends NonRegisteringDriver{
  
  public Driver() throws SQLException{
  
       }
  
       static{
  
           try{
  
               DriverManager.registerDriver(new Driver());
  
           }catch(SQLException E){
  
               throw new RuntimeException("Can't register driver!");
  
           }
  
  }
  
  }
  
  从源码中可以看出,com.mysql.jdbc.Driver是在类的static block里面做的初始化。
  
  那么我们只要搞清楚在java里面,static block执行的时机就可以清楚来龙去脉了。
  
  还是做一个实验吧!
  
  package com.javaye;
  
  class A{
  
       static{
  
                 System.out.println("Class A loaded");
  
        }
  
       public A(){
  
               System.out.println("create a instance of A");
  
        }
  
  }
  
  public class Main {
  
        public static void main(String[] args) throws Exception{
  
                   Class.forName("com.javaye.A");
  
       }
  
  }
  
  打印结果:“Class A loaded” 
  
  这说明Class.forName可以使类的static block中的代码得到执行。然后,我们在修改成下面这样:
  
  package com.javaye;
  
  class A{
  
   static{
  
   System.out.println("Class A loaded");
  
   }
  
   public A(){
  
     System.out.println("create a instance of A");
  
   }
  
  }
  
  public class Main {
  
  public static void main(String[] args) throws Exception{
  
     com.javaye.A a = null;
  
     }
  
  }
  
  发现没有打印任何东西,这说明只是声明某个类的变量,是不会使static block的到执行的。
  
  再改一下:
  
  package com.javaye;
  
  class A{
  
  static{
  
   System.out.println("Class A loaded");
  
   }
  
   public A(){
  
     System.out.println("create a instance of A");
  
   }
  
  }
  
  public class Main {
  
   public static void main(String[] args) throws Exception{
  
     com.javaye.A a = new com.javaye.A();
  
   com.javaye.A a2 = new com.javaye.A();
  
   }
  
  }
  
  输出结果:
  
  Class A loaded
  
  create a instance of A
  
  create a instance of A
  
  这说明实例化一个类的话,static block 也会被执行,而且只会被执行一遍。
  
  如果仍有兴趣,还可以探索一下Driver的注册机制:
  
  public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException {
  
   if (!initialized) {
  
       initialize();
  
   }
  
   DriverInfo di = new DriverInfo();
  
   di.driver = driver;
  
   di.driverClass = driver.getClass();
  
   di.driverClassName = di.driverClass.getName();
  
   drivers.addElement(di);    //drivers 是一个vector,保存着被注册的driver.
  
   println("registerDriver: " + di); 
  
  }
  
  getConnection就是要从drivers里面挑出一个合适的数据库driver:
  
  for (int i = 0; i < drivers.size(); i++) {
  
       DriverInfo di = (DriverInfo)drivers.elementAt(i);
  
       // If the caller does not have permission to load the driver then
  
       // skip it.
  
       if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
  
   println("    skipping: " + di);
  
     continue;
  
       }
  
       try {
  
     println("    trying " + di);
  
     Connection result = di.driver.connect(url, info);
  
     if (result != null) {
  
         // Success!
  
         println("getConnection returning " + di);
  
         return (result);
  
     }
  
       } catch (SQLException ex) {
  
     if (reason == null) {
  
         reason = ex;
  
     }
  
  }

本文为顽石科技原创转载请注明:
http://www.zrzxtime.com/html/2017/xiaoquxinwen_0906/560.html