基于javassist進(jìn)行動(dòng)態(tài)編程過(guò)程解析
今天在研究dubbo時(shí),發(fā)現(xiàn)一個(gè)新的知識(shí)點(diǎn),可以使用javassist包進(jìn)行動(dòng)態(tài)編程,hibernate也使用該包進(jìn)行編程。晚上百度了很多資料,將它的特性以代碼的形式展現(xiàn)出來(lái)。
package com.zhi.demo; import java.lang.reflect.Field; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtField; import javassist.CtMethod; import javassist.CtNewConstructor; import javassist.CtNewMethod; import javassist.Loader; import javassist.Modifier; import javassist.bytecode.AccessFlag; /** * Javassist動(dòng)態(tài)編程測(cè)試 * * @date 2019年03月11日23:00:33 * */ public class JavassistTest { public static void main(String[] args) { try { test(); } catch (Exception e) { e.printStackTrace(); } } private static void test() throws Exception { System.out.println("-------------------新增類------------------"); ClassPool pool = ClassPool.getDefault(); // 創(chuàng)建類 CtClass ct = pool.makeClass("com.zhi.Person"); // 讓類實(shí)現(xiàn)Cloneable接口 ct.setInterfaces(new CtClass[] { pool.makeInterface("java.lang.Cloneable") }); // 添加一個(gè)int類型的共有屬性 CtField fieldId = new CtField(CtClass.intType, "id", ct); fieldId.setModifiers(AccessFlag.PUBLIC); ct.addField(fieldId); // 添加一個(gè)默認(rèn)構(gòu)造器 CtConstructor constructor1 = CtNewConstructor.make("public Person(){this.id=1;}", ct); ct.addConstructor(constructor1); // 添加方法 CtMethod helloM = CtNewMethod .make("public void hello(String des){System.out.println(\"執(zhí)行hello方法,\"+des+\",我的id是\"+this.id);}", ct); ct.addMethod(helloM); // 將生成的.class文件保存到磁盤(pán) ct.writeFile(); // 加載目標(biāo)類,可用ct.toClass()或new Loader(pool).loadClass() Class<?> clazz = ct.toClass(); // Class<?> clazz = new Loader(pool).loadClass("com.zhi.Person"); // 輸出類基本信息 System.out.println("包名:" + clazz.getPackageName()); System.out.println("類名:" + clazz.getName()); System.out.println("簡(jiǎn)要類名:" + clazz.getSimpleName()); System.out.println("限定符:" + Modifier.toString(clazz.getModifiers())); System.out.println("繼承類:" + clazz.getSuperclass().getName()); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println("屬性名稱:" + field.getName() + ",屬性類型:" + field.getType() + ",限定符:" + Modifier.toString(field.getModifiers())); } // 構(gòu)造一個(gè)對(duì)象,并執(zhí)行hello方法 Object ob = clazz.getDeclaredConstructor().newInstance(); clazz.getMethod("hello", String.class).invoke(ob, "張三"); // 解凍(執(zhí)行toClass后會(huì)自動(dòng)凍結(jié)) ct.defrost(); System.out.println("-------------------修改類------------------"); // 添加一個(gè)String類型的私有屬性 CtField fieldName = new CtField(pool.get(String.class.getName()), "name", ct); fieldName.setModifiers(AccessFlag.PRIVATE); ct.addField(fieldName); // 添加帶參的構(gòu)造函數(shù) CtConstructor constructor2 = new CtConstructor(new CtClass[] { pool.get(String.class.getName()) }, ct); constructor2.setModifiers(Modifier.PUBLIC); constructor2.setBody("{this.name=$1;}"); ct.addConstructor(constructor2); ct.addMethod(CtNewMethod.make("public void setName(String name){this.name=name;}", ct)); ct.addMethod(CtNewMethod.make("public String getName(){return this.name;}", ct)); ct.writeFile(); // 加載類,若前面已用ct.toClass()進(jìn)行加載,則這里不能再用ct.toClass()加載,否則會(huì)出錯(cuò),同一個(gè)加載不能2次加載同一個(gè)類 clazz = new Loader(pool).loadClass("com.zhi.Person"); fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println("屬性名稱:" + field.getName() + ",屬性類型:" + field.getType() + ",限定符:" + Modifier.toString(field.getModifiers())); } ob = clazz.getDeclaredConstructor(String.class).newInstance("馬云"); System.out.println("執(zhí)行g(shù)etName方法得到的值為:" + clazz.getMethod("getName").invoke(ob)); } }
執(zhí)行上面代碼輸出結(jié)果為:
-------------------新增類------------------ 包名:com.zhi 類名:com.zhi.Person 簡(jiǎn)要類名:Person 限定符:public 繼承類:java.lang.Object 屬性名稱:id,屬性類型:int,限定符:public 執(zhí)行hello方法,張三,我的id是1 -------------------修改類------------------ 屬性名稱:id,屬性類型:int,限定符:public 屬性名稱:name,屬性類型:class java.lang.String,限定符:private 執(zhí)行g(shù)etName方法得到的值為:馬云
說(shuō)明:
$0,$1,$2:分別代表this,第一個(gè)參數(shù),第二個(gè)參數(shù)
$r:方法返回值的類型。
$_:方法返回值
依賴包
<dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.24.1-GA</version> </dependency>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaWeb實(shí)現(xiàn)簡(jiǎn)單用戶發(fā)送郵件
這篇文章主要為大家詳細(xì)介紹了JavaWeb實(shí)現(xiàn)簡(jiǎn)單用戶發(fā)送郵件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08vue用CryptoJS加密,java用CryptoUtil解密
CryptoJS是一個(gè)JavaScript庫(kù),提供了一系列密碼學(xué)函數(shù)和工具,用于加密、解密、生成摘要等任務(wù),本文vue前端使用CryptoJS加密,java后端使用CryptoUtil解密2024-09-09Java ThreadLocal 線程安全問(wèn)題解決方案
這篇文章主要介紹了Java ThreadLocal 線程安全問(wèn)題解決方案的相關(guān)資料,需要的朋友可以參考下2016-09-09基于java TCP網(wǎng)絡(luò)通信的實(shí)例詳解
本篇文章是對(duì)java中TCP網(wǎng)絡(luò)通信的實(shí)例進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05java+io+swing實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java+io+swing實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07mybatis自動(dòng)生成@Table、@Column、@Id注解的方法
這篇文章主要介紹了mybatis自動(dòng)生成@Table、@Column、@Id注解的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12@PathParam和@QueryParam區(qū)別簡(jiǎn)析
這篇文章主要介紹了@PathParam和@QueryParam區(qū)別,分享了相關(guān)實(shí)例代碼,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01