zoukankan      html  css  js  c++  java
  • JDBC为什么使用反射加载驱动

    一直不太明白在使用JDBC的时候用Class.forName("com.mysql.jdbc.Driver") 去加载驱动,就谷歌了一下,得到如下答案:


    前言

    JDBC源码地址
    还有
    在解释具体原因之前先简单看下Class.forName做了什么。假设一个类以前从来没有被装进内存过,Class.forName(String className)这个方法会做以下几件事情:
    1、装载。将字节码读入内存,并产生一个与之对应的java.lang.Class类对
    2、连接。这一步会验证字节码,为static变量分配内存,并赋默认值(0或null),并可选的解析符号引用(这里不理解没关系)
    3、初始化。为类的static变量赋初始值,假如有static int a = 1;这个将a赋值为1的操作就是这个时候做的。除此之外,还要调用类的static块。(这一步是要点)
    Class.forName(String className)方法会将这三步都做掉,

    基本原因

    首先,上面一段代码的主要作用,是在运行期以反射的方式来检查JDBC驱动的主类com.mysql.jdbc.Driver是否存在,若不存则表示运行环境中没有这个驱动,进入catch段。如果你确定一定以及肯定它会存在,可以直接写成

    import com.mysql.jdbc.Driver;
    

    效果基本是一样的(只是在编译期及运行期要都保证此类存在classpath中)
    所以,以反射形式加载的一个好处是当驱动jar包不存在时,我们可以做更多的操作。(要知道,在很久很久以前,jdbc驱动一般都是放在运行环境的classpath中的,如tomcat/lib)

    另一个原因

    如果你是一个有追求的程序员,那么另外一个很重要的原因是解耦。
    首先要明白JDBC是Java的一种规范,通俗一点说就是JDK在java.sql.*下提供了一系列的接口(interface),但没有提供任何实现(也就是类)。 所以任何人都可以在接口规范之下写自己的JDBC实现(如MySQL)。而若调用者也只调用接口上的方法(如我们),那么当未来有任何变更需要时(例如要从MySQL迁移至Oracle),则理论上不需要对代码做任何修改就能直接切换(可惜SQL语法没能统一规范)
    这意味着什么?意味着你的代码中不应该引用任何与实现相关的东西,你的代码只知道java.sql.*,而不应该知道com.mysql.*或是com.oracle.*,以避免或减少未来切换数据源时对代码的变更。
    注意,我们使用的所有其他API包括Connection/Statement/ResultSet等都是java.sql.*的东西,甚至com.mysql.jdbc.Driver类也是:

    package com.mysql.jdbc;
    public class Driver ... implements java.sql.Driver { ...}
    

    因此,直接import com.mysql.jdbc.Driver;
    违反了开闭原则(OCP,对扩展开放,对修改关闭)。(有人说我用反射也必须要修改代码呀,事实上你可以将类名字符串存储至.properties文件,和数据库用户名密码放在一起,就像Hibernate做的那样)

    原文地址:https://segmentfault.com/q/1010000000315618/a-1020000000317423
    http://www.ticmy.com/?p=249

  • 相关阅读:
    Linux之nginx服务
    设计模式-总结
    linux rabbitmq 远程登录
    swagger常用注解
    nginx总结
    mysql-sql
    dubbo-文档
    JVM总结-Java语法糖与Java编译器
    JVM总结-synchronized
    JVM总结-java内存模型
  • 原文地址:https://www.cnblogs.com/tenlee/p/5059813.html
Copyright © 2011-2022 走看看