一直不太明白在使用JDBC的時候用Class.forName("com.mysql.jdbc.Driver")
去加載驅動,就谷歌了一下,獲得以下答案:java
JDBC源碼地址
還有
在解釋具體緣由以前先簡單看下Class.forName作了什麼。假設一個類之前歷來沒有被裝進內存過,Class.forName(String className)這個方法會作如下幾件事情:
一、裝載。將字節碼讀入內存,併產生一個與之對應的java.lang.Class類對
二、鏈接。這一步會驗證字節碼,爲static變量分配內存,並賦默認值(0或null),並可選的解析符號引用(這裏不理解不要緊)
三、初始化。爲類的static變量賦初始值,假若有static int a = 1;這個將a賦值爲1的操做就是這個時候作的。除此以外,還要調用類的static塊。(這一步是要點)
Class.forName(String className)方法會將這三步都作掉,mysql
首先,上面一段代碼的主要做用,是在運行期以反射的方式來檢查JDBC驅動的主類com.mysql.jdbc.Driver
是否存在,若不存則表示運行環境中沒有這個驅動,進入catch段。若是你肯定必定以及確定它會存在,能夠直接寫成git
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
類也是:github
package com.mysql.jdbc; public class Driver ... implements java.sql.Driver { ...}
所以,直接import com.mysql.jdbc.Driver;
違反了開閉原則(OCP,對擴展開放,對修改關閉)。(有人說我用反射也必需要修改代碼呀,事實上你能夠將類名字符串存儲至.properties文件,和數據庫用戶名密碼放在一塊兒,就像Hibernate作的那樣)sql
原文地址:https://segmentfault.com/q/1010000000315618/a-1020000000317423
http://www.ticmy.com/?p=249數據庫