当前位置:首页 > 每日看点 > 正文内容

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

卡卷网1年前 (2025-01-11)每日看点207

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

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

分享给朋友:

相关文章

电视参数哪个最重要?

电视参数哪个最重要?

在选择智能电视时,面板类型是一个关键因素。IPS面板以其宽广的视角和出色的色彩还原能力受到青睐,尤其适合日常观看和游戏。尽管可能会有轻微的漏光,但在大多数情况下,这并不影响使用体验。相比之下,VA面板提供更高的对比度和更深的黑色,增强了沉浸...

国内比较好用的快速开发平台有哪些?

国内比较好用的快速开发平台有哪些?

低代码/零代码快速开发平台,一直是近年来很热的一个词,各大巨头的纷纷加入也给这个赛道。题主需要一个能二次开发的低代码快速开发平台,可以试试JVS低代码(私有化)。JVS低代码前端采用Vuex框架和Element-ui组件库,后端则基于Spr...

为什么我感受不到 1500 元的手机比四五千的差?

我长期使用两千元左右的安卓机,一天接近8小时的重度手机使用者。某天我突然想试试看传说中非常赛艇的苹果。狠了心,砸了钱。七千大样买了爱疯。就这?什么辣鸡玩意。而且因为我一直更新软件,用了两年爱疯就卡了。并没有传说中的用四五年不卡。用了这么一次...

打印速度慢,是不是打印机cpu不行?

打印速度慢,是不是打印机cpu不行?

打印机是机械设备,cpu内存硬盘它也有但这只是它的电控部分,打印机类似于汽车属于机电一体化设备和电脑不是一个类型的产品。很多人总是认为打印机和电脑是一类产品,实际上这是一个误区,电脑是it(Information Technology)信息...

Redmi 为什么可以把性价比做得那么高?

一位修手机的老大哥曾经跟我说过,红米1那个手机,除了处理器还凑活,其余零部件,就是市面上山寨机那种。其实红米性价比并不算极致,而且一直都有竞争者,从原来的群魔乱舞,到后来的荣耀,魅蓝,一加,再到现在的IQOO和realme。红米的方法也很简...

为什么工资五千的人会一下花八九千买手机呢?

这其实是一个何不食肉糜的问题,这个问题其实很现实,越是月薪5000越需要高档手机。 前段时间看了一个纪录片,讲外卖小哥都用什么手机,结果发现绝大多数外卖小哥用的手机都是旗舰机型,有的时候宁可买二手也要买旗舰。 因为1外卖小哥对ip6...

发表评论

访客

看不清,换一张

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