栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

浅谈Class.forName()在JDBC中的作用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

浅谈Class.forName()在JDBC中的作用

目录

1、Class.forName()有什么作用呢?

2、为什么不直接new?

3、为什么删除Class.forName("com.mysql.jdbc.Driver")还是可以运行?


JDBC是Bridge模式的典型应用,DriverManager就是其中的Abstraction;java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一个具体实现。前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。 Bridge模式中,Abstraction(DriverManager)是要拥有一个Implementor(Driver)的引用的。

一般,我们在连接数据库时,会使用如下的代码:

try {
    Class.forName("com.mysql.jdbc.Driver");
    connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
} catch (Exception e) {
    e.printStackTrace();
}

1、Class.forName()有什么作用呢?

首先,我们都知道,在java中Class.forName()方法在java中的作用是1、用于在JVM中查找并加载指定的类到内存中。2、初始化这个类

此时,我们将"com.mysql.jdbc.Driver"作为参数传入,是让JVM到"com.mysql.jdbc"路径下,找到Driver类并将其加载到内存中。

我们一起来看一下Driver类的详细代码:

public class Driver extends NonRegisteringDriver
  implements java.sql.Driver
{
  public Driver() throws SQLException{
  }
​
  static
  {
    try
    {
      DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
      throw new RuntimeException("Can't register driver!");
    }
  }
}

Class.forName(“com.mysql.jdbc.Driver”)的作用实际上就是调用DriverManager的 registerDriver方法注册一个mysql的JDBC驱动(Driver)而已(简而言之,就是将mysql驱动注册到DriverManager中去)。

其中调用的DriverManager的 registerDriver方法中的关键代码有:

private static final CopyOnWriteArrayList registeredDrivers =
 new CopyonWriteArrayList();

它的底层利用了一个CopyOnWriteArrayList作为容器(这是一个线程安全的容器,不过每次add的时候都会对底层数组进行一次新的复制,所以在读远多于写的时候建议可以使用这个),放那些注册进去的DriverInfo。最终getConnection(...)的时候就拿registerDrivers里面注册进去的具体的某个数据库的DriverInfo(像MySql的Driver就在DriverInfo里面)去连接具体的数据库。

整个流程就是:

JDK不负责和数据库连接打交道,也没必要,只提供一个具体的接口Driver,告诉所有第三方,要连接数据库,就去实现这个接口,然后通过DriverManager注册一下,到时候连接某个数据库的时候,你已经在我这里注册了,我会调用你注册进来的Driver里面的方法去对指定数据库进行连接的。然后Mysql就实现自己的Driver,Oracle就实现自己的Driver,通过static块注册一下,再然后,就没有然后了。

这样之后,我们就可以通过DriverManager的getConnection方 法获得mysql的连接了:

connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/test"
, "root", "root");

到此为止,我们就获得了connection对象,现在就可以对数据库进行操作了。

总而言之,我们只需要在调用DriverManager的getConnection方法之前,保证相应的Driver类已经被加载到jvm中,并且完成了类的初始化工作就行了,而具体是怎样实现这个功能却是没有讲究的。

2、为什么不直接new?

意思是这么写"com.mysql.jdbc.Driver d = new com.mysql.jdbc.Driver();",这样写也是可以的,因为在new的时候会自动触发对一个类的初始化。

但问题是new出来干嘛?com.mysql.jdbc.Driver里面的方法我们会用到吗,并且我们知道怎么用吗?仅仅为了初始化一个类而new一个类实例出来还不如不去new,直接使用Class.forName(String name)初始化就可以了。DriverManager类的getConnection(...)方法的存在本身就是帮助用户调用Driver里面的各种方法连接数据库,JDK都做好了,开发者就没必要自己写了。

特别要注意的是,如果我们进行如下操作,程序是不能正常运行的,因为这样仅仅使Driver类被装载到jvm中,却没有进行相应的初始化工作。

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

3、为什么删除Class.forName("com.mysql.jdbc.Driver")还是可以运行?

1996年1月23日JDK1.0发布,Java语言有了第一个正式版本的运行环境。JDBC是1997年2月19日,在JDK1.1的版本中发布的,从版本就看得出,JDBC属于Java技术的一些最基础的功能点。那在JDK1.5之后,其实已经不需要去显式调用Class.forName("com.mysql.jdbc.Driver")了,DriverManager会自动去加载合适的驱动,但是前提是CLASSPATH下必须有驱动jar包。

在DriverManager的源码中可以看到一个静态块:

 
    static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }

进入loadInitialDrivers()方法中看到以下一段代码:

private static void loadInitialDrivers() {
         String drivers;
         try {
             drivers = AccessController.doPrivileged(new PrivilegedAction() {
                 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(new PrivilegedAction() {
             public Void run() {
 
                 ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class);
                 Iterator driversIterator = loadedDrivers.iterator();
 
                 
                 try{
                     while(driversIterator.hasNext()) {
                         driversIterator.next();
                     }
                 } catch(Throwable t) {
                 // Do nothing
                 }
                 return null;
             }
         });

重点是这句代码:

ServiceLoader.load(Driver.class);

这行代码可以把类路径下所有jar包中meta-INF/services/java.sql.Driver文件中定义的类加载上来,此类必须继承自java.sql.Driver。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/678713.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号