a. 背景
很多时候,在写Java原生代码连接MySQL的时候,我们总能遇到一句神奇的代码行Class.forName("com.mysql.cj.jdbc.Driver");
,但这么多年了,我倒其实也不是很清楚它的背后起的是什么作用,如果让我猜,或许是建立一个DatabaseConnection
的时候需要使用到对应Driver
类中的某些参数or配置信息,而这又依托于这个类已经加载进Java内存空间中,所以通过Class.forName()
的方式进行预加载,不晓得我猜的对不对(我要开始Google了,咱今天就要把它搞透
b. Class.forName的背后
以上是Class.forName
的源码,API DOC表明来这个方法是用于将指定路径下的类进行初始化(执行类的静态变量初始化 & 静态方法块),并返回类对象,简单地理解,可以把这个过程理解成是注册在了Java的内存空间内,下次再需要到用这个类的静态资源时,可以直接使用!底层也使用到了Java的反射机制来获取是哪个类调用的这个方法,并使用调用这个方法的类的类加载器(ClassLoader)来加载这个目标类
c. com.mysql.cj.jdbc.Driver
如果使用的
mysql-connector-java
为5.x及其以下版本则MySQL的驱动类为com.mysql.jdbc.Driver
如果使用的
mysql-connector-java
为6.0以上版本则MySQL的驱动类为com.mysql.jdbc.Driver
Java SQL框架支持多个数据库驱动器,每一个不同的数据库都应该有自己的驱动类,而DriverManager
会尝试加载所能加载到的驱动器用于建立连接请求(也就是Connection
),而这个连接着是通过不同的Driver
驱动类建立得到,当一个驱动类被加载时,它会创建一个自己的单例并且把自己注册到DriverManager
中,意味着使用者也可以通过Class.forName
的方式手动做加载,而com.mysql.cj.jdbc.Driver
则是MySQL的驱动器
而手动Class.forName("com.mysql.cj.jdbc.Driver");
也如开篇所说,主要做的事情是将Driver
类加载至Java内存中,以便后续使用,Driver
在加载后主要是把自己注册到DriverManager
中,如下所示
然而这种手动加载的方式只有在JDBC 4.0前需要,在此后版本的DriverManager
中已经实现了主动加载机制,在拿到JDBC URL后会由DriverManager
主动load对应的驱动器,相关源码可查阅DriverManager.ensureDriversInitialized()
方法
d. 总结
- 最新版本(JDBC 4.0以上 & Java 6.0起)的JDBC已经不再需要手动做
Driver
的注册 - 现有的资料中,大部分示范代码都带有
Class.forName("com.mysql.cj.jdbc.Driver");
,主要是大量的copy-paste导致,对代码本身无任何影响,唯二的好处可能是当未存在对应驱动类时,会直接抛出对应异常,同时能够兼容旧版本的代码 mysql-connector-java
为5.x及其以下版本则MySQL的驱动类为com.mysql.jdbc.Driver
mysql-connector-java
为6.0以上版本则MySQL的驱动类为com.mysql.jdbc.Driver