13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

除了JDK、CGLIB,还有3种类代理方式

 五种类代理的方式

不出意外,你可能只知道两种类代理的方式。一种是JDK自带的,另外一种是CGLIB。

创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于成都网站制作、成都网站建设、前郭网络推广、微信小程序定制开发、前郭网络营销、前郭企业策划、前郭品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;创新互联公司为所有大学生创业者提供前郭建站搭建服务,24小时服务热线:18982081108,官方网址:www.cdcxhl.com

我们先定义出一个接口和相应的实现类,方便后续使用代理类在方法中添加输出信息。

「定义接口」

 
 
 
 
  1. public interface IUserApi { 
  2.  
  3.     String queryUserInfo(); 
  4.  

「实现接口」

 
 
 
 
  1. public class UserApi implements IUserApi { 
  2.  
  3.     public String queryUserInfo() { 
  4.         return "沉淀、分享、成长,让自己和他人都能有所收获!"; 
  5.     } 
  6.  

好!接下来我们就给这个类方法使用代理加入一行额外输出的信息。

0. 先补充一点反射的知识

 
 
 
 
  1. @Test 
  2. public void test_reflect() throws Exception { 
  3.     Class clazz = UserApi.class; 
  4.     Method queryUserInfo = clazz.getMethod("queryUserInfo"); 
  5.     Object invoke = queryUserInfo.invoke(clazz.newInstance()); 
  6.     System.out.println(invoke); 

1. JDK代理方式

 
 
 
 
  1. public class JDKProxy { 
  2.  
  3.     public static  T getProxy(Class clazz) throws Exception { 
  4.         ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
  5.         return (T) Proxy.newProxyInstance(classLoader, new Class[]{clazz}, new InvocationHandler() { 
  6.             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
  7.                 System.out.println(method.getName() + " 你被代理了,By JDKProxy!"); 
  8.                 return "沉淀、分享、成长,让自己和他人都能有所收获!"; 
  9.             } 
  10.         }); 
  11.     } 
  12.  
  13.  
  14. @Test 
  15. public void test_JDKProxy() throws Exception { 
  16.     IUserApi userApi = JDKProxy.getProxy(IUserApi.class); 
  17.     String invoke = userApi.queryUserInfo(); 
  18.     logger.info("测试结果:{}", invoke); 
  19.  
  20. /** 
  21.  * 测试结果: 
  22.  *  
  23.  * queryUserInfo 你被代理了,By JDKProxy! 
  24.  * 19:55:47.319 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果: 沉淀、分享、成长,让自己和他人都能有所收获! 
  25.  * 
  26.  * Process finished with exit code 0 
  27.  */ 

2. CGLIB代理方式

 
 
 
 
  1. public class CglibProxy implements MethodInterceptor { 
  2.     public Object newInstall(Object object) { 
  3.         return Enhancer.create(object.getClass(), this); 
  4.     } 
  5.     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 
  6.         System.out.println("我被CglibProxy代理了"); 
  7.         return methodProxy.invokeSuper(o, objects); 
  8.     } 
  9.  
  10. @Test 
  11. public void test_CglibProxy() throws Exception { 
  12.     CglibProxy cglibProxy = new CglibProxy(); 
  13.     UserApi userApi = (UserApi) cglibProxy.newInstall(new UserApi()); 
  14.     String invoke = userApi.queryUserInfo(); 
  15.     logger.info("测试结果:{}", invoke); 
  16.  
  17. /** 
  18.  * 测试结果: 
  19.  *  
  20.  * queryUserInfo 你被代理了,By CglibProxy! 
  21.  * 19:55:47.319 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果:  沉淀、分享、成长,让自己和他人都能有所收获! 
  22.  * 
  23.  * Process finished with exit code 0 
  24.  */ 

3. ASM代理方式

 
 
 
 
  1. public class ASMProxy extends ClassLoader { 
  2.  
  3.     public static  T getProxy(Class clazz) throws Exception { 
  4.  
  5.         ClassReader classReader = new ClassReader(clazz.getName()); 
  6.         ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS); 
  7.  
  8.         classReader.accept(new ClassVisitor(ASM5, classWriter) { 
  9.             @Override 
  10.             public MethodVisitor visitMethod(int access, final String name, String descriptor, String signature, String[] exceptions) { 
  11.  
  12.                 // 方法过滤 
  13.                 if (!"queryUserInfo".equals(name)) 
  14.                     return super.visitMethod(access, name, descriptor, signature, exceptions); 
  15.  
  16.                 final MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions); 
  17.  
  18.                 return new AdviceAdapter(ASM5, methodVisitor, access, name, descriptor) { 
  19.  
  20.                     @Override 
  21.                     protected void onMethodEnter() { 
  22.                         // 执行指令;获取静态属性 
  23.                         methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 
  24.                         // 加载常量 load constant 
  25.                         methodVisitor.visitLdcInsn(name + " 你被代理了,By ASM!"); 
  26.                         // 调用方法 
  27.                         methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); 
  28.                         super.onMethodEnter(); 
  29.                     } 
  30.                 }; 
  31.             } 
  32.         }, ClassReader.EXPAND_FRAMES); 
  33.  
  34.         byte[] bytes = classWriter.toByteArray(); 
  35.  
  36.         return (T) new ASMProxy().defineClass(clazz.getName(), bytes, 0, bytes.length).newInstance(); 
  37.     } 
  38.  
  39.  
  40. @Test 
  41. public void test_ASMProxy() throws Exception { 
  42.     IUserApi userApi = ASMProxy.getProxy(UserApi.class); 
  43.     String invoke = userApi.queryUserInfo(); 
  44.     logger.info("测试结果:{}", invoke); 
  45.  
  46. /** 
  47.  * 测试结果: 
  48.  *  
  49.  * queryUserInfo 你被代理了,By ASM! 
  50.  * 20:12:26.791 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果: 沉淀、分享、成长,让自己和他人都能有所收获! 
  51.  * 
  52.  * Process finished with exit code 0 
  53.  */ 

4. Byte-Buddy代理方式

 
 
 
 
  1. public class ByteBuddyProxy { 
  2.  
  3.     public static  T getProxy(Class clazz) throws Exception { 
  4.  
  5.         DynamicType.Unloaded dynamicType = new ByteBuddy() 
  6.                 .subclass(clazz) 
  7.                 .method(ElementMatchers.named("queryUserInfo")) 
  8.                 .intercept(MethodDelegation.to(InvocationHandler.class)) 
  9.                 .make(); 
  10.  
  11.         return (T) dynamicType.load(Thread.currentThread().getContextClassLoader()).getLoaded().newInstance(); 
  12.     } 
  13.  
  14.  
  15. @RuntimeType 
  16. public static Object intercept(@Origin Method method, @AllArguments Object[] args, @SuperCall Callable callable) throws Exception { 
  17.     System.out.println(method.getName() + " 你被代理了,By Byte-Buddy!"); 
  18.     return callable.call(); 
  19.  
  20. @Test 
  21. public void test_ByteBuddyProxy() throws Exception { 
  22.     IUserApi userApi = ByteBuddyProxy.getProxy(UserApi.class); 
  23.     String invoke = userApi.queryUserInfo(); 
  24.     logger.info("测试结果:{}", invoke); 
  25.  
  26. /** 
  27.  * 测试结果: 
  28.  *  
  29.  * queryUserInfo 你被代理了,By Byte-Buddy! 
  30.  * 20:19:44.498 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果: 沉淀、分享、成长,让自己和他人都能有所收获! 
  31.  * 
  32.  * Process finished with exit code 0 
  33.  */ 

5. Javassist代理方式

 
 
 
 
  1. public class JavassistProxy extends ClassLoader { 
  2.  
  3.     public static  T getProxy(Class clazz) throws Exception { 
  4.  
  5.         ClassPool pool = ClassPool.getDefault(); 
  6.         // 获取类 
  7.         CtClass ctClass = pool.get(clazz.getName()); 
  8.         // 获取方法 
  9.         CtMethod ctMethod = ctClass.getDeclaredMethod("queryUserInfo"); 
  10.         // 方法前加强 
  11.         ctMethod.insertBefore("{System.out.println(\"" + ctMethod.getName() + " 你被代理了,By Javassist\");}"); 
  12.  
  13.         byte[] bytes = ctClass.toBytecode(); 
  14.  
  15.         return (T) new JavassistProxy().defineClass(clazz.getName(), bytes, 0, bytes.length).newInstance(); 
  16.     } 
  17.  
  18.  
  19. @Test 
  20. public void test_JavassistProxy() throws Exception { 
  21.     IUserApi userApi = JavassistProxy.getProxy(UserApi.class) 
  22.     String invoke = userApi.queryUserInfo(); 
  23.     logger.info("测试结果:{}", invoke); 
  24.  
  25. /** 
  26.  * 测试结果: 
  27.  *  
  28.  * queryUserInfo 你被代理了,By Javassist 
  29.  * 20:23:39.139 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果: 沉淀、分享、成长,让自己和他人都能有所收获! 
  30.  * 
  31.  * Process finished with exit code 0 
  32.  */ 

四、总结


当前名称:除了JDK、CGLIB,还有3种类代理方式
本文URL:http://cdbrznjsb.com/article/cdhschp.html

其他资讯

让你的专属顾问为你服务