卡卷网
当前位置:卡卷网 / 每日看点 / 正文

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

作者:卡卷网发布时间:2025-01-10 19:14浏览数量:74次评论数量:0次

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

JDK

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

//目标接口 pulicinteceUserServ{ voidaddUser(Stringname); } //目标类 pulicclassUserServImplimplementsUserServ{ @Override pulicvoidaddUser(Stringname){ System.out.println("添加用户:"+name); } } //处理器 pulicclassLogInvocationHandlerimplementsInvocationHandler{ privatefinalOjecttarget; pulicLogInvocationHandler(Ojecttarget){ this.target=target; } @Override pulicOjectinvoke(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{ @Override pulicOjectintercept(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{ @Override pulicvoidaddUser(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

pulicclassADemo{ pulicstaticvoidmain(String[]args){ //创建ClassWriter ClassWritercw=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、使用难度:

2、性能较:

3、应用场景:

4、局限性:

选择建议

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

免责声明:本文由卡卷网编辑并发布,但不代表本站的观点和立场,只提供分享给大家。

评论 打赏
卡卷网

卡卷网 主页 联系他吧

请记住:卡卷网 Www.Kajuan.Net

相关推荐

欢迎 发表评论:

请填写验证码