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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM