类代理的方式有哪些

发布时间:2021-10-26 09:25:15 作者:iii
来源:亿速云 阅读:153

这篇文章主要讲解了“类代理的方式有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“类代理的方式有哪些”吧!

 五种类代理的方式

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

「定义接口」

public interface IUserApi {      String queryUserInfo();  }

「实现接口」

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

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

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

@Test public void test_reflect() throws Exception {     Class<UserApi> clazz = UserApi.class;     Method queryUserInfo = clazz.getMethod("queryUserInfo");     Object invoke = queryUserInfo.invoke(clazz.newInstance());     System.out.println(invoke); }

1. JDK代理方式

public class JDKProxy {      public static <T> T getProxy(Class clazz) throws Exception {         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();         return (T) Proxy.newProxyInstance(classLoader, new Class[]{clazz}, new InvocationHandler() {             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                 System.out.println(method.getName() + " 你被代理了,By JDKProxy!");                 return "沉淀、分享、成长,让自己和他人都能有所收获!";             }         });     }  }  @Test public void test_JDKProxy() throws Exception {     IUserApi userApi = JDKProxy.getProxy(IUserApi.class);     String invoke = userApi.queryUserInfo();     logger.info("测试结果:{}", invoke); }  /**  * 测试结果:  *   * queryUserInfo 你被代理了,By JDKProxy!  * 19:55:47.319 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果: 沉淀、分享、成长,让自己和他人都能有所收获!  *  * Process finished with exit code 0  */

2. CGLIB代理方式

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

3. ASM代理方式

public class ASMProxy extends ClassLoader {      public static <T> T getProxy(Class clazz) throws Exception {          ClassReader classReader = new ClassReader(clazz.getName());         ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);          classReader.accept(new ClassVisitor(ASM5, classWriter) {             @Override             public MethodVisitor visitMethod(int access, final String name, String descriptor, String signature, String[] exceptions) {                  // 方法过滤                 if (!"queryUserInfo".equals(name))                     return super.visitMethod(access, name, descriptor, signature, exceptions);                  final MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);                  return new AdviceAdapter(ASM5, methodVisitor, access, name, descriptor) {                      @Override                     protected void onMethodEnter() {                         // 执行指令;获取静态属性                         methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");                         // 加载常量 load constant                         methodVisitor.visitLdcInsn(name + " 你被代理了,By ASM!");                         // 调用方法                         methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);                         super.onMethodEnter();                     }                 };             }         }, ClassReader.EXPAND_FRAMES);          byte[] bytes = classWriter.toByteArray();          return (T) new ASMProxy().defineClass(clazz.getName(), bytes, 0, bytes.length).newInstance();     }  }  @Test public void test_ASMProxy() throws Exception {     IUserApi userApi = ASMProxy.getProxy(UserApi.class);     String invoke = userApi.queryUserInfo();     logger.info("测试结果:{}", invoke); }  /**  * 测试结果:  *   * queryUserInfo 你被代理了,By ASM!  * 20:12:26.791 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果: 沉淀、分享、成长,让自己和他人都能有所收获!  *  * Process finished with exit code 0  */

4. Byte-Buddy代理方式

public class ByteBuddyProxy {      public static <T> T getProxy(Class clazz) throws Exception {          DynamicType.Unloaded<?> dynamicType = new ByteBuddy()                 .subclass(clazz)                 .method(ElementMatchers.<MethodDescription>named("queryUserInfo"))                 .intercept(MethodDelegation.to(InvocationHandler.class))                 .make();          return (T) dynamicType.load(Thread.currentThread().getContextClassLoader()).getLoaded().newInstance();     }  }  @RuntimeType public static Object intercept(@Origin Method method, @AllArguments Object[] args, @SuperCall Callable<?> callable) throws Exception {     System.out.println(method.getName() + " 你被代理了,By Byte-Buddy!");     return callable.call(); }  @Test public void test_ByteBuddyProxy() throws Exception {     IUserApi userApi = ByteBuddyProxy.getProxy(UserApi.class);     String invoke = userApi.queryUserInfo();     logger.info("测试结果:{}", invoke); }  /**  * 测试结果:  *   * queryUserInfo 你被代理了,By Byte-Buddy!  * 20:19:44.498 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果: 沉淀、分享、成长,让自己和他人都能有所收获!  *  * Process finished with exit code 0  */

5. Javassist代理方式

public class JavassistProxy extends ClassLoader {      public static <T> T getProxy(Class clazz) throws Exception {          ClassPool pool = ClassPool.getDefault();         // 获取类         CtClass ctClass = pool.get(clazz.getName());         // 获取方法         CtMethod ctMethod = ctClass.getDeclaredMethod("queryUserInfo");         // 方法前加强         ctMethod.insertBefore("{System.out.println(\"" + ctMethod.getName() + " 你被代理了,By Javassist\");}");          byte[] bytes = ctClass.toBytecode();          return (T) new JavassistProxy().defineClass(clazz.getName(), bytes, 0, bytes.length).newInstance();     }  }  @Test public void test_JavassistProxy() throws Exception {     IUserApi userApi = JavassistProxy.getProxy(UserApi.class)     String invoke = userApi.queryUserInfo();     logger.info("测试结果:{}", invoke); }  /**  * 测试结果:  *   * queryUserInfo 你被代理了,By Javassist  * 20:23:39.139 [main] INFO  org.itstack.interview.test.ApiTest - 测试结果: 沉淀、分享、成长,让自己和他人都能有所收获!  *  * Process finished with exit code 0  */

感谢各位的阅读,以上就是“类代理的方式有哪些”的内容了,经过本文的学习后,相信大家对类代理的方式有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. 实现JavaScript编写类的方式有哪些
  2. 有哪些类代理的方式

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jdk java

上一篇:Linux Fedora 8系统安装过程中如何创建一个IE

下一篇:Samba怎么安装

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》