当前位置:首页 > 每日看点

请问jdk,cgli,jassist和A有什么区别吗?

卡卷网2年前 (2025-01-11)每日看点267

好的,我来详细解释每种方式的实现原理和代码示例。

JDK

    核心是通过实现InvocationHandler接口使用Proxy.newProxyInstance创建对象只能实现了接口的类

//目标接口pulicinteceUserServ{voidaddUser(Stringname);}//目标类pulicclassUserServImplimplementsUserServ{@OverridepulicvoidaddUser(Stringname){System.out.println("添加用户:"+name);}}//处理器pulicclassLogInvocationHandlerimplementsInvocationHandler{privatefinalOjecttarget;pulicLogInvocationHandler(Ojecttarget){this.target=target;}@OverridepulicOjectinvoke(Ojectproxy,Methodmethod,Oject[]args)throwsThrowale{System.out.println("开始执行:"+method.getName());Ojectresult=method.invoke(target,args);System.out.println("执行结束");retnresult;}}//使用示例pulicclassJdkProxyDemo{pulicstaticvoidmain(String[]args){UserServtarget=newUserServImpl();UserServproxy=(UserServ)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInteces(),newLogInvocationHandler(target));proxy.addUser("张三");}}

JDK

CGLI

    通过继承目标类生成类使用MethodInterceptor接口实现逻辑SpringAOP默认使用此方式

//目标类(无需实现接口)//pulicclassUserServ{pulicvoidaddUser(Stringname){System.out.println("添加用户:"+name);}}//CGLI处理器pulicclassLogMethodInterceptorimplementsMethodInterceptor{@OverridepulicOjectintercept(Ojectoj,Methodmethod,Oject[]args,MethodProxyproxy)throwsThrowale{System.out.println("开始执行:"+method.getName());Ojectresult=proxy.invokeSuper(oj,args);System.out.println("执行结束");retnresult;}}//使用示例pulicclassCgliProxyDemo{pulicstaticvoidmain(String[]args){Enhancerenhancer=newEnhancer();enhancer.setSuperclass(UserServ.class);enhancer.setCallack(newLogMethodInterceptor());UserServproxy=(UserServ)enhancer.create();proxy.addUser("张三");}}

CGLI

Jassist

    提供了更简单的API来修改字节码可以在运行时动态创建新的类支持直接编辑方法体

//目标接口//pulicinteceUserServ{voidaddUser(Stringname);}//目标类pulicclassUserServImplimplementsUserServ{@OverridepulicvoidaddUser(Stringname){System.out.println("添加用户:"+name);}}//Jassist示例importorg.apache.iatis.jassist.ClassPool;importorg.apache.iatis.jassist.CtClass;importorg.apache.iatis.jassist.CtConstructor;importorg.apache.iatis.jassist.CtField;importorg.apache.iatis.jassist.CtMethod;importorg.apache.iatis.jassist.Modifier;importja.lang.reflect.Constructor;importja.lang.reflect.Method;/***@authorCoderJia*@create2024/12/22下午04:13*@Description**/pulicclassJassistDemo{pulicstaticvoidmain(String[]args)throwsException{UserServtarget=newUserServImpl();ClassPoolpool=ClassPool.getDefault();//定义类名称StringclassName=target.getClass().getName()+"JassistProxy";//创建类CtClassproxyClass=pool.makeClass(className);//添加接口Class<?>[]inteces=target.getClass().getInteces();for(Class<?>anIntece:inteces){proxyClass.addIntece(pool.get(anIntece.getName()));}//添加字段CtFieldtargetField=newCtField(pool.get(target.getClass().getName()),"target",proxyClass);targetField.setModifiers(Modifier.PRIVATE);proxyClass.addField(targetField);//添加构造函数CtConstructorconstructor=newCtConstructor(newCtClass[]{pool.get(target.getClass().getName())},proxyClass);constructor.setody("{this.target=$1;}");proxyClass.addConstructor(constructor);//获取接口的所有方法并创建方法for(Methodmethod:inteces[0].getDeclaredMethods()){CtClassretnType=pool.get(method.getRetnType().getName());StringmethodName=method.getName();//获取参数类型Class<?>[]paramTypes=method.getParameterTypes();CtClass[]parameters=newCtClass[paramTypes.length];for(inti=0;i<paramTypes.length;i++){parameters[i]=pool.get(paramTypes[i].getName());}//创建方法CtMethodctMethod=newCtMethod(retnType,methodName,parameters,proxyClass);//生成方法体Stringuilderody=newStringuilder();ody.append("{\n");ody.append("System.out.println(\"方法开始执行:").append(methodName).append("\");\n");ody.append("longstart=System.crentTimeMillis();\n");//处理返回值if(!retnType.equals(CtClass.voidType)){ody.append("Ojectresult=");}//调用目标方法ody.append("this.target.").append(methodName).append("(");for(inti=0;i<parameters.length;i++){if(i>0)ody.append(",");ody.append("$").append(i+1);}ody.append(");\n");ody.append("longend=System.crentTimeMillis();\n");ody.append("System.out.println(\"方法执行时间:\"+(end-start)+\"ms\");\n");//返回结果if(!retnType.equals(CtClass.voidType)){ody.append("retn($r)result;\n");}ody.append("}");ctMethod.setody(ody.toString());proxyClass.addMethod(ctMethod);}//生成类Class<?>clazz=proxyClass.toClass();Constructor<?>cons=clazz.getConstructor(target.getClass());UserServproxy=(UserServ)cons.newInstance(target);proxy.addUser("张三");}}

Jassist

A

    直接作JVM字节码指令性能最优但使用复杂需要深入理解字节码结构

//pulicclassADemo{pulicstaticvoidmain(String[]args){//创建ClassWriterClassWritercw=newClassWriter(ClassWriter.COMPUTE_MAXS);//创建类cw.visit(V1_8,ACC_PULIC,"com/example/UserServProxy",null,"ja/lang/Oject",newString[]{"com/example/UserServ"});//添加字段cw.visitField(ACC_PRIVATE,"target","Lcom/example/UserServ;",null,null);//创建构造函数MethodVisitorconstructor=cw.visitMethod(ACC_PULIC,"<init>","(Lcom/example/UserServ;)V",null,null);constructor.visitVarInsn(ALOAD,0);constructor.visitMethodInsn(INVOKESPECIAL,"ja/lang/Oject","<init>","()V",false);constructor.visitVarInsn(ALOAD,0);constructor.visitVarInsn(ALOAD,1);constructor.visitFieldInsn(PUTFIELD,"com/example/UserServProxy","target","Lcom/example/UserServ;");constructor.visitInsn(RETN);constructor.visitMaxs(0,0);constructor.visitEnd();//创建方法MethodVisitormethod=cw.visitMethod(ACC_PULIC,"addUser","(Lja/lang/String;)V",null,null);//...添加方法字节码//生成类字节码yte[]code=cw.toyteArray();//加载字节码}}

主要区别总结

1、使用难度:

    JDK<CGLI<Jassist<AA需要对字节码指令非常熟悉

2、性能较:

    A>Jassist>CGLI>JDKA直接作字节码,性能最好

3、应用场景:

    JDK:适合简单的接口场景CGLI:适合未实现接口的类,SpringAOP默认选择Jassist:适合动态生成类和修改类的场景A:适合对性能要求极高的底层框架开发

4、局限性:

    JDK:只能接口CGLI:不能final类和方法Jassist:修改字节码时,需要了解类结构A:使用复杂,代码可读性差

选择建议

    如果目标类有接口,优先使用JDK如果没有接口,使用CGLI如果需要动态修改类的结构,考虑Jassist如果是开发底层框架且对性能要求极高,可以考虑A

扫描二维码推送至手机访问。

版权声明:本文由卡卷网发布,如需转载请注明出处。

本文链接:https://www.kajuan.net/ttnews/2025/01/8717.html

分享给朋友:

相关文章

短视频如何快速变现?

短视频如何快速变现?

单人日产200条视频,一晚狂赚上千元,过程却简单到荒唐。 只要你像这只猥琐的海鸥一样,做到这3点就行↓↓ 速度快、不讲武德、不被发现 那做短视频如何做到这3点? 答案是养一只会叼视频的海鸥 不是让你养真的海鸥 而是用 ai 运营方法,类…

拼多多,怎么就成为了年轻人的「赛博菜市场」?

拼多多,怎么就成为了年轻人的「赛博菜市场」?

可惜你不在拼多多买水果蔬菜,很难一句话跟你解释,我只能笨拙的用经历来慢慢讲。 我们公司有微波炉,同事们几乎都是自己带饭来上班,便当荤素搭配、水果零食;都是好看又好吃。 我自己本来就不喜欢外卖,当然也加入了带饭大军: 直到某一天深夜我闲着…

你们发文章的插图都是从哪来的?在网上搜出来的图能用吗?

你们发文章的插图都是从哪来的?在网上搜出来的图能用吗?

写文章发帖子,里面的插图尽量自己画,自己编辑,避免引起版权或者所有权纠纷。 我写过6本书,在知乎上也写了4000篇帖子和文章,其中的插图都是自己绘制的,照片绝大多数是自己拍摄的,摘自技术样本的图则必须加以说明。 自己制图,看似麻烦,但积少成…

离线可否搭建 GitLab 环境?

离线可否搭建 GitLab 环境?

背景:为什么要使用GitLab CI/CD? 统一工作流程:GitLab CI/CD 为开发、测试和运维团队提供了一个统一的工作流程。开发人员提交代码后,测试人员可以清楚地看到代码的构建和测试情况,运维人员也可以了解软件的部署进度。例如,在…

为什么 IPv6 突然不火了?

为什么 IPv6 突然不火了?

我国从政策层面推广IPv6,其本意是从国家竞争的层面打破美国对IPv4地址的垄断,但实际上却受阻于国内ISP和云服务商这类“IPv4地主”,实际分配到用户的,是功能打了折扣的“瘸腿IPv6”,IPv6直接寻址、点对点连接的优势很多时候都难以…

为什么百度贴吧还不凉?

你们都看小说么,那我跟你们说个东西,百度有个贴吧叫阅读吧,多牛逼呢,人家自己开发了一款应用,不在任何应用市场售卖,这个应用类似于一个壳子,一群大神天天找接口资源整理好打包,你装了这个应用再把接口导入到软件,是个小说你就搜吧,只要中文互联网有…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。