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

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

卡卷网7个月前 (01-11)每日看点111

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

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

分享给朋友:

相关文章

CDN评测,阿里云有对手了!腾讯云优势明显

CDN评测,阿里云有对手了!腾讯云优势明显

         如今,云计算产品越来越多,像国内的BAT三大巨头都提供了云主机(腾讯云CVM、阿里云ECS、百度云BCC),另外还有存储、数据库、安全等相关云服务。在这其中,CDN也是一项重要的云服...

电脑c盘哪些文件可以删除?

电脑c盘哪些文件可以删除?

电脑上的文件夹都是英文,很多朋友都不敢乱删,下面这几个文件夹里的文件,你可以放心删除。一、可删除的文件1、Backup这是一个备份文件夹,很多装机软件经常会把需要备份的东西,放在这个文件夹中。而当我们需要的软件正常保存之后,这些东西也就没有...

现在做抖音的话,还有机会嘛?

现在做抖音的话,还有机会嘛?

之前我问过小杨哥一个问题:“现在抖音还好做吗?”疯狂小杨哥在抖音已经突破1亿粉丝,直播间10w的在线观看人数,日常带货随便一场也是上7位数的数据。现在抖音的市场好像已经被头部占领,资源靠前,普通人似乎已经没有机会了?下面是小杨哥对于做抖音的...

为何 Linus 一个人就能写出这么强的系统,中国却做不出来?

为何 Linus 一个人就能写出这么强的系统,中国却做不出来?

我给你举个真实的例子。。有一个人叫高伟东,在哈尔滨工作。在2012年做了一个APP。使用词根词缀背单词。名字叫:词根词缀词典这个人编辑了2300余条词根,给10万多条单词建立了词根索引,整理了50多万条的单词记忆方法,包括新版本的诸多新功能...

我爸讽刺我,写个破代码一年才十几万,他在工地带50个人,让我回去跟他干,写代码没出路,我该怎么选择?

我跟你一样的情况,本人现身说法,千万不要跟你爸干,我就是反面教材,现在想回去都回不去了,快十年没写代码了,再就是岁数大了,38岁了,35岁以上的码农根本就没公司愿意要,而且会受歧视。工程不好干,首先就是不合法,在法律层面,根本就没有包工头的...

夸克浏览器受欢迎的原因是什么?

夸克浏览器受欢迎的原因是什么?

这是可以说的嘛~哈哈,它比较吸引我的几点是:安全无广、页面简洁、功能丰富、反应速度快......首页页面支持自定义,喜欢什么样子都可以自己调整,没有花里胡哨的各种资讯推送,热搜日报整理归纳好,想看再点开查看,看着舒适度直接拉满!实用日常工具...

发表评论

访客

看不清,换一张

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