[MyBatis源碼分析 - 反射器模塊]

一、背景介紹

??MyBatis作為一個ORM框架诵棵,一個核心的功能是數(shù)據(jù)庫數(shù)據(jù)和Java POJO(即Java Bean)之間的轉(zhuǎn)換,MyBatis是基于JDBC封裝的,先來看一段簡單的JDBC代碼嚣潜。

    public Role getRole(Long id) {
        Connection connection = getConnection();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = connection.prepareStatement("select id, role_name, note from t_role where id = ?");
            ps.setLong(1, id);
            rs = ps.executeQuery();
            while (rs.next()) {
                Long roleId = rs.getLong("id");
                String roleName = rs.getString("role_name");
                String note = rs.getString("note");
                Role role = new Role();
                role.setId(id);
                role.setRoleName(roleName);
                role.setNote(note);
                return role;
            }
        } catch (Exception e) {
            Logger.getLogger(JdbcExample.class.getName()).log(Level.SEVERE, null, e);
        } finally {
            this.close(rs, ps, connection);
        }
        return null;
    }

??從上面代碼可以看到JDBC執(zhí)行一條帶參數(shù)的SQL時,要有傳入的參數(shù)值id椅贱,還要知道參數(shù)值的類型Long懂算,這樣才知道要調(diào)用PreparedStatement對象的setLong方法。MyBatis執(zhí)行SQL時庇麦,一般傳入的參數(shù)類型是一個Java Bean计技,設(shè)置SQL參數(shù)往往是用到Java Bean的部分成員屬性,獲取參數(shù)值通過屬性的getter方法獲取山橄,屬性類型需要通過反射獲取垮媒,一般簡單使用的Java Bean的屬性是跟數(shù)據(jù)庫數(shù)據(jù)表的字段對應(yīng)的,eg:

public class Role {
    private long id;
    private String roleName;
    private String note;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getRoleName() {
        return roleName;
    }
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
}

POJO對應(yīng)的數(shù)據(jù)表結(jié)構(gòu)

??當(dāng)然航棱,在更加復(fù)雜的業(yè)務(wù)模型中睡雇,POJO和表結(jié)構(gòu)不是簡單的一對一關(guān)系,可能一個POJO組合在另一個POJO中饮醇,常見于表關(guān)聯(lián)產(chǎn)生的一對一它抱、一對多映射中。POJO成員屬性的數(shù)據(jù)類型雖然常見是基本類型的包裝類(不建議直接使用基本類型如int朴艰、long观蓄,而是使用它們的包裝類IntegerLong祠墅,因?yàn)榛绢愋蜁心J(rèn)值侮穿,而包裝類型是對象默認(rèn)為null),但也有可能是集合類型如List(比如一對多一個訂單下有多個商品)毁嗦,還可能是Map(當(dāng)然Map更多用在傳參而不是成員屬性類型或者POJO類型這種語義不強(qiáng)的場景)亲茅。

??如果業(yè)務(wù)模型注重建模,POJO可能還會有繼承關(guān)系,繼承意味子類也繼承了父類的屬性芯急,還有更復(fù)雜的情況勺届,為了靈活使用,一些父類中的屬性類型可能會被設(shè)計(jì)成泛型娶耍,形式可能為<T>(普通泛型)免姿、<T extends Xxx><T super Yyy>(限制泛型)榕酒、<? extends Xxx>胚膊、<? super Yyy>(通配符泛型),這些都增加了POJO和數(shù)據(jù)表數(shù)據(jù)轉(zhuǎn)換的難度想鹰,因?yàn)閳?zhí)行SQL設(shè)置參數(shù)紊婉、SQL執(zhí)行結(jié)果映射轉(zhuǎn)化為Java對象,都需要知道實(shí)際使用時屬性的確切類型辑舷,還有調(diào)用相應(yīng)屬性的setter喻犁、getter,這些都需要依賴Java的反射API來實(shí)現(xiàn)何缓。

Java反射API雖然功能強(qiáng)大肢础,但編寫出高質(zhì)量的反射代碼難度較高,比較復(fù)雜且容易出錯碌廓,為了簡化反射操作的相關(guān)代碼传轰,MyBatis提供了專門的反射模塊,該模塊對 Java 原生的反射進(jìn)行了良好的封裝谷婆,提了更加簡潔易用的 API慨蛙,方便上層使調(diào)用,并且對反射操作進(jìn)行了一系列優(yōu)化纪挎,比如將類的元信息封裝緩存在MetaClass對象中期贫,提高了反射操作的性能。

??反射模塊的代碼一覽如下:



二廷区、功能概述

??根據(jù)上面的背景介紹和需求分析總結(jié)唯灵,反射器模塊需要實(shí)現(xiàn)的功能有:

  • 1、獲取類的元信息隙轻,包括:構(gòu)造方法埠帕、可讀/可寫的所有屬性、屬性對應(yīng)的getter/setter方法
  • 2玖绿、根據(jù)類元信息創(chuàng)建Java對象敛瓷,主要是在執(zhí)行完SQL將數(shù)據(jù)轉(zhuǎn)化為Java對象時用到

??關(guān)于相關(guān)組件介紹的系列文章如下:


三、Reflector

??Reflector是整個反射器模塊的基礎(chǔ)斑匪,通過其解析類的元信息并緩存起來呐籽,源碼解析詳見:[MyBatis源碼分析 - 反射器模塊 - 組件一] Reflector


四、Invoker

??Invoker 是一個接口狡蝶,緩存了類屬性對應(yīng)的 Field 對象和 getter/setter 方法對應(yīng)的 Method 對象庶橱,設(shè)置獲取屬性值、調(diào)用方法贪惹,實(shí)際上是調(diào)用 Field 對象和 Method 對象的反射方法去完成苏章,Reflector 中的 getMethodssetMethods 屬性緩存了屬性和對應(yīng)的 Invoker 對象的映射奏瞬,源碼解析詳見:[MyBatis源碼分析 - 反射器模塊 - 組件二] Invoker枫绅。


五、ObjectFactory

??ObjectFactory 從名字上看很容器猜出用途硼端,對象工廠就是用來創(chuàng)建對象的并淋,MyBatis 中會使用該類來創(chuàng)建所有需要的新對象,源碼解析詳見:[MyBatis源碼分析 - 反射器模塊 - 組件三] ObjectFactory珍昨。


六县耽、TypeParameterResolver

??TypeParameterResolver 是一個類型參數(shù)解析器,即JavaBean中可能帶泛型如 List<T>曼尊、通配符如 <? super SubClass>酬诀,而且可能復(fù)雜的繼承關(guān)系脏嚷,為了獲取到運(yùn)行時正確具體的類型(包括屬性類型骆撇、方法參數(shù)類型、方法返回值類型)父叙,需要使用該類解析類型參數(shù)神郊,源碼解析詳見:[[MyBatis源碼分析 - 反射器模塊 - 組件四] TypeParameterResolver]


七趾唱、Property 工具集

??主要有三個工具類:PropertyCopier涌乳、PropertyNamerPropertyTokenizer甜癞。分別用來拷貝對象屬性值夕晓、從方法名提取屬性信息、解析屬性表達(dá)式悠咱,源碼解析詳見:[MyBatis源碼分析 - 反射器模塊 - 組件五] Property 工具集蒸辆。


八、MetaClass

??MetaClass 通過對 ReflectorPropertyTokenizer 組合使用析既,實(shí)現(xiàn)了對復(fù)雜的屬性表達(dá)式的解析躬贡,并實(shí)現(xiàn)了獲取指定屬性描述信息的功能,源碼解析詳見:[MyBatis源碼分析 - 反射器模塊 - 組件六] MetaClass眼坏。

九拂玻、ObjectWrapper

??ObjectWrapper 接口是對對象的包裝,抽象了對象的屬性信息,它定義了一系列查詢對象屬性信息檐蚜、以及更新屬性的方法魄懂,源碼解析詳見:[MyBatis源碼分析 - 反射器模塊 - 組件七] ObjectWrapper

十闯第、MetaObject

??MetaObject 封裝了 ObjectWrapper 對象和相應(yīng)配套的工廠對象逢渔,主要聯(lián)合實(shí)現(xiàn)對表達(dá)式的解析和配套的操作,形成一組完成的操作對象的方法乡括,其源碼解析詳見:[MyBatis源碼分析 - 反射器模塊 - 組件八] MetaObject肃廓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市诲泌,隨后出現(xiàn)的幾起案子盲赊,更是在濱河造成了極大的恐慌,老刑警劉巖敷扫,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哀蘑,死亡現(xiàn)場離奇詭異,居然都是意外死亡葵第,警方通過查閱死者的電腦和手機(jī)绘迁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來卒密,“玉大人缀台,你說我怎么就攤上這事∠妫” “怎么了膛腐?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鼎俘。 經(jīng)常有香客問我哲身,道長,這世上最難降的妖魔是什么贸伐? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任勘天,我火速辦了婚禮,結(jié)果婚禮上捉邢,老公的妹妹穿的比我還像新娘脯丝。我一直安慰自己,他們只是感情好歌逢,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布巾钉。 她就那樣靜靜地躺著,像睡著了一般秘案。 火紅的嫁衣襯著肌膚如雪砰苍。 梳的紋絲不亂的頭發(fā)上潦匈,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機(jī)與錄音赚导,去河邊找鬼茬缩。 笑死,一個胖子當(dāng)著我的面吹牛吼旧,可吹牛的內(nèi)容都是我干的凰锡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼圈暗,長吁一口氣:“原來是場噩夢啊……” “哼掂为!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起员串,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤勇哗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后寸齐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體欲诺,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年渺鹦,在試婚紗的時候發(fā)現(xiàn)自己被綠了扰法。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡毅厚,死狀恐怖塞颁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卧斟,我是刑警寧澤殴边,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站珍语,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏竖幔。R本人自食惡果不足惜板乙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拳氢。 院中可真熱鬧募逞,春花似錦、人聲如沸馋评。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽留特。三九已至纠脾,卻和暖如春玛瘸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苟蹈。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工糊渊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人慧脱。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓渺绒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親菱鸥。 傳聞我的和親對象是個殘疾皇子宗兼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359