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

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

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

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

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

分享给朋友:

相关文章

中国CEO直播简史

中国CEO直播简史

  领导人爱对外发言这事,是中国的一个传统文化。  从乾隆爱往名画上盖章上,就可见一斑。  3Q大战时代,微博成了大佬“吵架”的战场,饭否变成了部分爱面子者的日记。  某种程度上说,互联网公关行业的诞生,和大佬们爱发言有着直接的关系。只不过...

Layui 不更新了么?

Layui 不更新了么?

layui2.8已经于今天正式发布了,新增优化了大量特性,这里按照layui更新日志的模块结构,详细为你一一介绍。基础风格调整新版调整主色调为#16baaa,在原有的墨绿基础上赋予了清新。更简单的构建构建代码更简单,除字体外,只有js和cs...

中国芯片产量达1399亿颗,这意味着什么?

美国并不是没有明白人,只是特朗普不懂芯片产业的情况,冒冒失失在ZZ正确下,开启了对中国芯片的掐脖子,结果没掐死,反而让人练出了铁肺。芯片是所有科技产业的上游,美国原本在上游呆得很舒服,靠英伟达、AMD、德州仪器、高通等这些几十年霸主地位的公...

闲鱼上为什么会有人问都不问直接下单?

我去年卖一个荣耀90,挂的2200,最终成交2137.5元。对方是一个高高壮壮的西北口音,要求的自取。大概我吃过午饭,约了旁边的商场,那里有荣耀售后。见了面,先看了手机,试了好一会儿,各种测试,没问题。然后去了商场二楼的荣耀售后,让人家售后...

鸿蒙到底是不是安卓套壳?

鸿蒙到底是不是安卓套壳?

把它是不是套壳先放在一边吧。我讲一个事情,大家自己判断。华为有一个应用,叫手机管家。这个手机管家对一些系统底层设置有影响:比如华为从 EMUI 9 开始不允许将第三方启动器设置为默认启动器,依靠的就是这个手机管家。为什么这么说呢?在网上搜索...

在追求家居美学的过程中,如何选择一款电视机,使其既具备出色的音画质又能与家居装饰相得益彰?

在追求家居美学的过程中,如何选择一款电视机,使其既具备出色的音画质又能与家居装饰相得益彰?

先看照片,你就说美不美吧?我家这个40平的客厅东西放得不少,其中最提升观感的是各种灯光,在这么多灯光中,是不是第一眼视觉中心就落在了电视上?没错,因为这电视是非常特别的环景光电视,与显示器的神光同步一样,会随着画面的变化而变化不同的光效,它...

发表评论

访客

看不清,换一张

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