日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

APM - Javassist 入门 生成一个简单类

發(fā)布時(shí)間:2025/3/21 java 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 APM - Javassist 入门 生成一个简单类 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 官網(wǎng)
  • 概述
  • Javassist作用
  • 常用API
  • Javassist 語(yǔ)法
  • Javassist使用流程
  • Demo
  • Demo2
  • 注意事項(xiàng)
  • 參考


官網(wǎng)

http://www.javassist.org/

http://www.javassist.org/tutorial/tutorial.html


概述

Javassist是一個(gè)開(kāi)源的分析、編輯和創(chuàng)建Java字節(jié)碼的類庫(kù),可以直接編輯和生成Java生成的字節(jié)碼。

相對(duì)于bcel, asm等這些工具,開(kāi)發(fā)者不需要了解虛擬機(jī)指令,就能動(dòng)態(tài)改變類的結(jié)構(gòu),或者動(dòng)態(tài)生成類。

Javassist簡(jiǎn)單易用, 快速。


Javassist作用

  • 運(yùn)行時(shí)監(jiān)控插樁埋點(diǎn)
  • AOP動(dòng)態(tài)代理實(shí)現(xiàn)(性能上比Cglib生成的要慢)
  • 獲取訪問(wèn)類結(jié)構(gòu)信息:如獲取參數(shù)名稱信息

常用API

類說(shuō)明
ClassPoolJavassist的類池,使用ClassPool 類可以跟蹤和控制所操作的類, 與 JVM ClassLoader相似
CtClassCtClass提供了類的操作,如在類中動(dòng)態(tài)添加新字段、方法和構(gòu)造函數(shù)、以及改變類、父類和接口的方法。
CtMethod類中的方法,通過(guò)它可以給類創(chuàng)建新的方法,還可以修改返回類型,訪問(wèn)修飾符等, 甚至還可以修改方法體內(nèi)容代碼
CtConstructor構(gòu)造函數(shù)
CtField類的屬性,通過(guò)它可以給類創(chuàng)建新的屬性,還可以修改已有的屬性的類型,訪問(wèn)修飾符等

Javassist 語(yǔ)法

項(xiàng)目Value
$0, $1, $2, …this and actual parameters
$argsAn array of parameters. The type of $args is Object[].
$$All actual parameters.For example, m($$) is equivalent to m($1,$2,…)
$cflow(…)cflow variable
$rThe result type. It is used in a cast expression.
$wThe wrapper type. It is used in a cast expression.
$_The resulting value
$sigAn array of java.lang.Class objects representing the formal parameter types
$typeA java.lang.Class object representing the formal result type.
$classA java.lang.Class object representing the class currently edited.


Javassist使用流程


Demo

依賴

<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.18.1-GA</version></dependency> import javassist.*;/*** 使用Javassist 構(gòu)建 一個(gè)新的類 并執(zhí)行*/ public class FirstJavasisit {public static void main(String[] args) throws CannotCompileException,NotFoundException, InstantiationException, IllegalAccessException {ClassPool pool = new ClassPool(true);// 插入類路徑,通過(guò)類路徑去搜索我們要的類pool.insertClassPath(new LoaderClassPath(FirstJavasisit.class.getClassLoader()));// 構(gòu)建一個(gè)新的CtClass對(duì)象CtClass targetClass = pool.makeClass("com.artisan.Hello");// 實(shí)現(xiàn)一個(gè)接口targetClass.addInterface(pool.get(IHello.class.getName()));// 獲取返回類型CtClass returnType = pool.get(void.class.getName());// 方法名稱String mname = "sayHello";// 方法參數(shù)CtClass[] parameters = new CtClass[]{pool.get(String.class.getName())};// 實(shí)例化方法CtMethod method = new CtMethod(returnType, mname, parameters, targetClass);// 方法中的源碼String src = "{"+ "System.out.println($1);"+ "}";// 設(shè)置src到方法中method.setBody(src);// 添加方法targetClass.addMethod(method);// 裝在到當(dāng)前的ClassLoader中Class cla = targetClass.toClass();// 實(shí)例化IHello hello = (IHello) cla.newInstance();// 方法調(diào)用hello.sayHello("artisan");}/*** 接口不是必須的,只是為了方便演示,少寫(xiě)點(diǎn)反射代碼*/public interface IHello {void sayHello(String name);} }


Demo2

讓我們對(duì)UserService類 插裝一下

package com.artisan.agent;public class UserService {/*** 無(wú)參方法* @throws InterruptedException*/public void sayHello() throws InterruptedException {Thread.sleep(100);System.out.println("hello 小工匠");}/*** 無(wú)返回值的* @param name* @param age* @param other* @throws InterruptedException*/public void say2Void(String name,int age,Object other) throws InterruptedException {Thread.sleep(100);System.out.println("hello 小工匠2");}/*** 帶有返回值* @param name* @param age* @param other* @return* @throws InterruptedException*/public String say2(String name,int age,Object other) throws InterruptedException {Thread.sleep(100);System.out.println("hello 小工匠2 with return ");return "ttttt";} }
@Testpublic void test3() throws NotFoundException, CannotCompileException, InterruptedException {// 類加載器ClassPool classPool = new ClassPool();// 追加系統(tǒng)ClassLoaderclassPool.appendSystemPath();// 獲取要操作的類CtClass ctClass = classPool.get("com.artisan.agent.UserService");// 獲取方法CtMethod originMethod = ctClass.getDeclaredMethod("say2Void");// copy 一個(gè)新的方法CtMethod newMethod = CtNewMethod.copy(originMethod,ctClass,null);// 設(shè)置新名字originMethod.setName(originMethod.getName()+ "$agent");// 對(duì)原方法進(jìn)行包裝,比如加計(jì)算方法耗時(shí)newMethod.setBody("{ long begin = System.currentTimeMillis();\n" +" say2Void$agent($$);\n" +" long end = System.currentTimeMillis();\n" +" System.out.println(end - begin);" +"}");// 將新方法添加到單簽類中ctClass.addMethod(newMethod);//把修改后的class裝載到JVMctClass.toClass();new com.artisan.agent.UserService().say2Void("art2",18,"xxxx");}@Testpublic void test4() throws NotFoundException, CannotCompileException, InterruptedException {// 類加載器ClassPool classPool = new ClassPool();// 追加系統(tǒng)ClassLoaderclassPool.appendSystemPath();// 獲取要操作的類CtClass ctClass = classPool.get("com.artisan.agent.UserService");// 獲取方法CtMethod originMethod = ctClass.getDeclaredMethod("say2");// copy 一個(gè)新的方法CtMethod newMethod = CtNewMethod.copy(originMethod,ctClass,null);// 設(shè)置新名字originMethod.setName(originMethod.getName()+ "$agent");// 對(duì)原方法進(jìn)行包裝,比如加計(jì)算方法耗時(shí) 帶有返回值的的 $rnewMethod.setBody("{ long begin = System.currentTimeMillis();\n" +" say2$agent($$);\n" +" long end = System.currentTimeMillis();\n" +" System.out.println(end - begin);" +" Object s = \"test\" ;" +" return ($r)s ;" +"}");// 將新方法添加到單簽類中ctClass.addMethod(newMethod);//把修改后的class裝載到JVMctClass.toClass();System.out.println((new com.artisan.agent.UserService().say2("art2", 18, "xxxx")));}


注意事項(xiàng)

  • 所引用的類型,必須通過(guò)ClassPool獲取后才可以使用
  • 代碼塊中所用到的引用類型,使用時(shí)必須寫(xiě)全量類名
  • 代碼塊內(nèi)容寫(xiě)錯(cuò)了,只有在運(yùn)行時(shí)才報(bào)錯(cuò)
  • javassist只接受單個(gè)語(yǔ)句或用大括號(hào)括起來(lái)的語(yǔ)句塊
  • 動(dòng)態(tài)修改的類,必須在修改之前,jvm中不存在這個(gè)類的實(shí)例對(duì)象。修改方法的實(shí)現(xiàn)必須在修改的類加載之前進(jìn)行

參考

https://baijiahao.baidu.com/s?id=1660843613132087355&wfr=spider&for=pc

https://www.cnblogs.com/scy251147/p/11100961.html

https://blog.csdn.net/21aspnet/article/details/81671777

https://www.cnblogs.com/rickiyang/p/11336268.html

總結(jié)

以上是生活随笔為你收集整理的APM - Javassist 入门 生成一个简单类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。