Eclipse下Javassist正確使用方法代碼解析
這兩天看到Hibernate的代理部分,第一反應(yīng)是底層使用了反射,針對(duì)用戶實(shí)體生成了代理類,后來(lái)反應(yīng)過(guò)來(lái)了,反射沒(méi)有任何可以產(chǎn)生新類的能力,也就順理成章地找到了Javassist(下載地址)。
在網(wǎng)上搜索到的大部分教程,都是針對(duì)Javassist的API進(jìn)行一番講解,但是最后,往往沒(méi)有一個(gè)加載過(guò)程,而筆者模仿這些教程進(jìn)行類的加載時(shí),加載到的結(jié)果都是原來(lái)的類,并沒(méi)有產(chǎn)生字節(jié)碼被修改的內(nèi)容。
在經(jīng)過(guò)一番探索后,筆者發(fā)現(xiàn),網(wǎng)上的大部分教程中的最后一步,保存字節(jié)碼,使用的均是writeFile的無(wú)參數(shù)重載,在查看其函數(shù)結(jié)構(gòu)后發(fā)現(xiàn),它還有一個(gè)String類型的重載,由于在Eclipse下,字節(jié)碼儲(chǔ)存的根位置并不是”.\\”而是”.\\bin”,而writeFile的另一個(gè)重載很可能是指定字節(jié)碼根位置的參數(shù),筆者進(jìn)行一番更改后發(fā)現(xiàn),果不其然。
下面將演示代碼分享出來(lái):
這是筆者項(xiàng)目的結(jié)構(gòu):

Editable.java:
package com.thrblock.javassist;
public class Editable {
public void showInfo(){
System.out.println("InfoDefault!");
}
}
Main.java:
package com.thrblock.javassist;
import java.io.IOException;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
public class Main {
public static void main(String[] args) {
ClassPool pool = ClassPool.getDefault();
try{
pool.insertClassPath(".\\bin");
//設(shè)置根路徑。(這里設(shè)置的根路徑顯然沒(méi)被writeFile使用)
CtClass cc = pool.makeClass("com.thrblock.javassist.EditableChanged");
//模擬Hibernate代理模式,我們創(chuàng)建一個(gè)新類
cc.setSuperclass(pool.get("com.thrblock.javassist.Editable"));
//設(shè)置其父類
CtMethodcm = CtNewMethod.make("public void showInfo(){super.showInfo();System.out.println(\"CustomInsertHAHA!\");}",cc);
//追加一個(gè)方法,注意它覆蓋了父類中的方法。
cc.addMethod(cm);
cc.writeFile(".\\bin");
//這里比較重要,空參的結(jié)果就是沒(méi)有保存到eclipse字節(jié)碼根路徑里。
}
catch (NotFoundException | CannotCompileException | IOException e) {
e.printStackTrace();
}
try{
Class<?> cl = Class.forName("com.thrblock.javassist.EditableChanged");
//加載我們的新類
Editableed = (Editable) cl.newInstance();
//由于其繼承與Editable類,這里和Hibernate里的load道理一樣。
ed.showInfo();
//調(diào)用方法。
}
catch (ClassNotFoundException | InstantiationException |IllegalAccessException e) {
e.printStackTrace();
}
}
}
打印結(jié)果:
InfoDefault!
CustomInsertHAHA!
其他注意事項(xiàng):
由于我們是生成了一個(gè)類,如果這個(gè)類名和原類名一樣,則會(huì)覆蓋class文件,但是如果修改之前該class已經(jīng)被JVM裝入,則修改的部分不會(huì)生效,必須重啟JVM。
總結(jié)
以上就是本文關(guān)于Eclipse下Javassist正確使用方法代碼解析的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!
相關(guān)文章
Java Validation Api如何實(shí)現(xiàn)自定義注解
這篇文章主要介紹了Java Validation Api如何實(shí)現(xiàn)自定義注解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
springboot自帶的緩存@EnableCaching用法
這篇文章主要介紹了springboot自帶的緩存@EnableCaching用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
IDEA上運(yùn)行Flink任務(wù)的實(shí)戰(zhàn)教程
這篇文章主要介紹了IDEA上運(yùn)行Flink任務(wù)的實(shí)戰(zhàn)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
SpringBoot@Profile注解和Spring?EL(多環(huán)境注入)
為了方便, Spring還提供了 Profile機(jī)制, 使我們可以很方便地實(shí)現(xiàn)各個(gè)環(huán)境之間的切換,在使用DI來(lái)依賴注入的時(shí)候,能夠根據(jù)@profile標(biāo)明的環(huán)境,將注入符合當(dāng)前運(yùn)行環(huán)境的相應(yīng)的bean,本文通過(guò)示例代碼介紹SpringBoot@Profile注解和Spring?EL,需要的朋友可以參考下2024-02-02

