zoukankan      html  css  js  c++  java
  • JDBC剖析篇(1):java中的Class.forName()

    一、Class.forName()

    在Java中我们一般用下面这样的语句来连接数据库(以MySQL为例)

    Class.forName("com.mysql.jdbc.Driver");
    con=DriverManager.getConnection("jdbc:mysql://"+dbServerIP+":"+dbPort+"/"+dbName,userName,passWord);

    其实我们还可以这样:

    com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();
    con=DriverManager.getConnection("jdbc:mysql://"+dbServerIP+":"+dbPort+"/"+dbName,userName,passWord);

    或者:

    new com.mysql.jdbc.Driver();
    con=DriverManager.getConnection("jdbc:mysql://"+dbServerIP+":"+dbPort+"/"+dbName,userName,passWord);

      在java中使用JDBC连接数据库时,我们需要知道下面这些信息,却很少去一探究竟

        (1)数据库类型:MySQL、SQL Server、Oracle等

        (2)驱动程序jar包:相应的数据库驱动jar包,如mysql-connector-java-5.1.5-bin.jar等

        (3)驱动类:com.mysql.jdbc.Driver

        (4)JDBC URL:jdbc:mysql:// dbServerIP:dbPort/dbName

      从前面的程序段中我们知道,只要在调用DriverManager的getConnection方法之前,保证相应的Driver类已经被加载到jvm中并且完成了类的初始化工作,程序就可以正常运行了。

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

    com.mysql.jdbc.Driver driver = null;

    或者:

    ClassLoader cl = new ClassLoader();   
    cl.loadClass("com.mysql.jdbc.Driver");

    二、Bridge模式

      JDBC是使用Bridge模式进行设计的,DriverManager是其中的Abstraction(业务抽象角色,公司),java.sql.Driver是Implementor(业务实现角色,产品),com.mysql.jdbc.Driver是Implementor的一个具体实现(某个具体的产品,衣服);需要注意的是,前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。

      Bridge模式中,Abstraction(DriverManager)是要拥有一个Implementor(Driver)的引用的,但是我们在使用过程中,并没有将Driver对象注册到DriverManager中去,这是怎么回事呢?

      JDK文档对Driver的描述如下图所示:

    从上图的描述可知com.mysql.jdbc.Driver在装载后自动帮我们完成了创建实例、注册等步骤,根据上述分析可知,按如下方式修改JDBC驱动的装载,程序同样可以执行:

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

    即有:

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

    ClassLoader.loadClass(xxx.xx.xx)仅加载某个类,但并没有实例化;Class.forName(String className)这个方法会做以下几件事情:装载、连接、初始化

    Class.forName(xxx.xx.xx) 返回一个类,与 new 的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。


    三、Driver的源代码

    com.mysql.jdbc.Driver的源代码如下:

    package com.mysql.jdbc;
    
    import java.sql.SQLException;
    
    public class Driver extends NonRegisteringDriver implements java.sql.Driver {
        // ~ Static fields/initializers
        // ---------------------------------------------
    
        //
        // Register ourselves with the DriverManager
        //
        static {
            try {
                java.sql.DriverManager.registerDriver(new Driver());
            } catch (SQLException E) {
                throw new RuntimeException("Can't register driver!");
            }
        }
    
        // ~ Constructors
        // -----------------------------------------------------------
    
        /**
         * Construct a new driver and register it with DriverManager
         * 
         * @throws SQLException
         *             if a database error occurs.
         */
        public Driver() throws SQLException {
            // Required for Class.forName().newInstance()
        }
    }

    扩展A

    现有下面这样一道题目,考察对驱动程序的认识

    题目解析:


    扩展B

    jvm在加载类的时候是不会执行静态代码的,只有在初始化的时候才会去执行


    参考资料

    (1)http://www.ticmy.com/?p=249

    (2)http://www.cnblogs.com/sunzn/p/3187868.html

  • 相关阅读:
    解决electron-vue中无法使用Element的Tooltip组件
    解决Electron安装包下载慢的问题
    虚拟机VirtualBox 共享挂载问题:mount: /mnt/xxx: wrong fs type, bad option, bad superblock on xxx
    git 设置和取消代理
    (转载)数据库连接池到底应该设多大?这篇文章可能会颠覆你的认知
    MySQL主主复制+MMM实现高可用
    Mysql5.6主从热备配置
    java 启动 shell脚本
    redis批量删除key
    spring mvc异常统一处理(ControllerAdvice注解)
  • 原文地址:https://www.cnblogs.com/studyLog-share/p/4710685.html
Copyright © 2011-2022 走看看