jooq_jOOQ星期二:拉斐尔·温特豪德(Rafael Winterhalter)正在与字节好友合作字节码...
jooq
歡迎來(lái)到j(luò)OOQ Tuesdays系列。 在本系列文章中,我們每隔一個(gè)月的第三個(gè)星期二發(fā)布一篇文章,從jOOQ的角度采訪我們發(fā)現(xiàn)該行業(yè)令人興奮的人。 這包括從事SQL,Java,開(kāi)放源代碼以及各種其他相關(guān)主題的人員。
我們很高興在第七版中與Rafael Winterhalter進(jìn)行交談,他將向我們介紹Java字節(jié)代碼的深度以及他的庫(kù)Byte Buddy,該庫(kù)使使用字節(jié)碼的工作變得非常容易 。
請(qǐng)注意,Byte Buddy贏得了2015年“杜克選擇獎(jiǎng)” -對(duì)此我們表示祝賀!
字節(jié)好友的作用是什么?
字節(jié)伙伴是一個(gè)代碼生成和操作庫(kù)。 它提供了API,用于在運(yùn)行時(shí)創(chuàng)建新的Java類以及在加載之前或之后更改現(xiàn)有的類。
乍一看,這聽(tīng)起來(lái)似乎很深?yuàn)W,但是運(yùn)行時(shí)代碼生成已在許多Java項(xiàng)目中使用。 庫(kù)開(kāi)發(fā)人員通常使用代碼生成工具來(lái)實(shí)現(xiàn)面向方面的編程。 例如, 模擬庫(kù)Mockito使用Byte Buddy在運(yùn)行時(shí)創(chuàng)建模擬類的子類。 為了實(shí)現(xiàn)模擬,Mockito會(huì)覆蓋類的所有方法,以便在測(cè)試中調(diào)用某個(gè)方法時(shí),不會(huì)調(diào)用用戶的原始代碼。 還有許多其他知名的代碼生成用戶。 例如,Spring使用代碼生成來(lái)實(shí)現(xiàn)其注釋方面,例如安全性或事務(wù)。 而且,Hibernate使用代碼生成通過(guò)覆蓋那些getter來(lái)延遲從getter方法中加載屬性,以僅在調(diào)用它們時(shí)才查詢數(shù)據(jù)庫(kù)。
當(dāng)有諸如ASM,CGLIB,AspectJ或Javassist之類的替代方案時(shí),為什么需要Byte Buddy?
在開(kāi)始從事Byte Buddy的工作之前,我曾作為貢獻(xiàn)者參與了其他幾個(gè)開(kāi)源項(xiàng)目。 如前所述,代碼生成是實(shí)現(xiàn)許多庫(kù)的典型要求,因此我習(xí)慣了使用CGLIB和Javassist 。 但是,我對(duì)這些庫(kù)的局限性不斷感到沮喪,我想解決我發(fā)現(xiàn)的問(wèn)題。 最終,我開(kāi)始寫(xiě)一個(gè)替代庫(kù),后來(lái)以Byte Buddy的形式發(fā)布。
要了解替代庫(kù)的局限性,模擬是一個(gè)很好的示例用例。 Mockito中的小樣以前是使用CGLIB創(chuàng)建的。 CGLIB是一個(gè)相當(dāng)成熟的庫(kù)。 它已經(jīng)存在了15年以上,當(dāng)它最初被開(kāi)發(fā)時(shí),圖書(shū)館的開(kāi)發(fā)人員當(dāng)然并沒(méi)有想到諸如注釋,通用類型或防御方法之類的功能。 但是,注釋確實(shí)成為許多不接受模擬實(shí)例的API的重要組成部分,因?yàn)樗兄貙?xiě)方法的注釋都會(huì)丟失。 在Java中,方法的注釋在被覆蓋時(shí)永遠(yuǎn)不會(huì)繼承。 并且類型的注釋只有在明確聲明為時(shí)才繼承。 為了克服這個(gè)問(wèn)題,Byte Buddy允許將任何注釋復(fù)制到子類中,該子類現(xiàn)在是Mockito 2中的功能。
相反,Javassist允許復(fù)制注釋,但我個(gè)人不喜歡該庫(kù)的方法。 在Javassist中,所有生成的代碼都表示為包含在字符串中的Java代碼。 結(jié)果,Javassist代碼的結(jié)構(gòu)類似于非結(jié)構(gòu)化的Java代碼,后者僅將SQL描述為級(jí)聯(lián)字符串。 除了創(chuàng)建難以維護(hù)的代碼外,此方法還提供了漏洞,例如類似于SQL注入的Java代碼注入。 有時(shí)可以通過(guò)允許Javassist代碼編譯任意代碼來(lái)攻擊Javassist代碼,這可能會(huì)對(duì)應(yīng)用程序造成嚴(yán)重?fù)p害。
在處理現(xiàn)有代碼時(shí), AspectJ是一個(gè)功能強(qiáng)大的工具。 但是,通過(guò)Byte Buddy,您可以用普通的簡(jiǎn)單Java來(lái)執(zhí)行AspectJ能夠執(zhí)行的任何操作。 這樣,開(kāi)發(fā)人員無(wú)需學(xué)習(xí)新的語(yǔ)法或編程隱喻,也無(wú)需為其構(gòu)建過(guò)程和IDE安裝工具。 此外,我認(rèn)為連接點(diǎn)和切入點(diǎn)術(shù)語(yǔ)并不直觀,因此決定完全避免使用。 相反,我決定模仿開(kāi)發(fā)人員已經(jīng)從Java編程語(yǔ)言中了解的術(shù)語(yǔ),以簡(jiǎn)化Byte Buddy的第一步。
另一方面, ASM是實(shí)現(xiàn)Byte Buddy的基礎(chǔ)。 ASM是字節(jié)代碼解析器,而不是代碼生成庫(kù)。 ASM處理單個(gè)類文件,并且不考慮類型層次結(jié)構(gòu)。 ASM既沒(méi)有類加載的概念,也沒(méi)有在字節(jié)碼指令之上包括更高級(jí)別的概念。 但是,Byte Buddy提供了一個(gè)適配器,該適配器向需要生成非常特定的代碼的用戶公開(kāi)ASM API。
如何參與低級(jí)Java?
一開(kāi)始,我為自己設(shè)定了僅創(chuàng)建具有注釋支持的CGLIB版本的目標(biāo),這正是我最初需要的。 但是我很快發(fā)現(xiàn),許多開(kāi)發(fā)人員正在尋找Byte Buddy如今已成為的解決方案。 因此,我開(kāi)始計(jì)劃使Java虛擬機(jī)的完整功能集可訪問(wèn)。 為此,學(xué)習(xí)類文件格式的所有細(xì)節(jié)和極端情況已成為實(shí)現(xiàn)這些功能的必要條件。 公平地講,一旦掌握了類文件格式,它就顯得微不足道了,我真的很高興看到我的庫(kù)成熟。
您最感覺(jué)到家在哪里?
我想為正確的工作使用正確的工具。 顯然,我喜歡使用字節(jié)碼,但是在生產(chǎn)項(xiàng)目中工作時(shí),我會(huì)避免手工制作字節(jié)碼。 最后,這是諸如Byte Buddy之類的更高級(jí)抽象的目的。
從常見(jiàn)的用例來(lái)看,但是Byte Buddy通常用于通過(guò)基于方法的注釋更改代碼來(lái)實(shí)現(xiàn)自定義功能。 從某種意義上說(shuō),Byte Buddy使開(kāi)發(fā)人員能夠?qū)崿F(xiàn)自己的4G抽象。 聲明式編程是某些任務(wù)的絕佳抽象,SQL是其中之一。
作為網(wǎng)紅,您最激動(dòng)人心的故事是什么?
主要是,我很高興認(rèn)識(shí)我的圖書(shū)館用戶。 我遇到了一些與大型團(tuán)隊(duì)一起實(shí)施基于我的軟件的內(nèi)部框架的人,很顯然,讓Byte Buddy證明如此有用使我感到驕傲。
非常感謝拉斐爾
如果您想了解有關(guān)Rafael的工作,字節(jié)碼或Byte Buddy的更多信息 ,請(qǐng)查看他在JavaZone上的演講:
翻譯自: https://www.javacodegeeks.com/2015/12/jooq-tuesdays-rafael-winterhalter-wrestling-byte-code-byte-buddy.html
jooq
總結(jié)
以上是生活随笔為你收集整理的jooq_jOOQ星期二:拉斐尔·温特豪德(Rafael Winterhalter)正在与字节好友合作字节码...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python kotlin_Java和P
- 下一篇: 神奇宝贝电脑桌面背景(神奇宝贝手机背景图