zoukankan      html  css  js  c++  java
  • 聊聊、动态代理

    动态代理大家都不陌生,生活中也有很多动态代理的例子,例如:香港代购。我们只需要说产品名称,代购就可以把产品从香港买回来给我们。

    微服务特别火,基本上每个公司都会涉及到。微服务的调用却是离不开 RPC 框架,从 RMI、WEBSERVICE、到今天的 Dubbo、GRPC、Thrift、SpringCloud等等。我们调用远程服务就像是调用本地服务一样,其实这些 RPC 框架给我们做了很多的事情,这些事情对我们来说是透明的。而代理技术,就是这些事情的核心功能。

    JDK动态代理 


    JDK动态代理是 JDK 反射机制实现的,首先实现 InvocationHandler 接口

    1.InvocationHandler 

    package org.jdkproxy;

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;

    public class JDKProxyInvoker implements InvocationHandler {

    private Object object;

    public JDKProxyInvoker(Object object) {
    this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("===invoke before===");
    Object result = method.invoke(object, args);
    System.out.println("===invoke after===");
    return result;
    }
    }

    2.IUser.java

    package org.PO;

    public interface IUser {
    public String sayHello();
    }

    3.UserImpl.java 

    package org.PO;

    public class UserImpl implements IUser {

    @Override
    public String sayHello() {
    System.out.println("===sayHello===");
    return "UserImpl hello";
    }
    }

    4.Main 

    IUser iUser = (IUser) Proxy.newProxyInstance(M.class.getClassLoader(),new Class[]{IUser.class},new JDKProxyInvoker(new UserImpl()));
    System.out.println(iUser.sayHello());

    5.结果

    6.Proxy.newProxyInstance原理 

    byte[] b = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{IUser.class});
    FileOutputStream outputStream = null;
    try {
    outputStream = new FileOutputStream("src/main/java/org/jdkproxy/$Proxy0.class");
    outputStream.write(b);
    outputStream.flush();
    outputStream.close();
    } catch (Exception e) {
    e.printStackTrace();
    }

    7.$Proxy0.class 

    public final class $Proxy0 extends Proxy implements IUser {

    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0; 

    static {
    try {
    m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
    m3 = Class.forName("org.PO.IUser").getMethod("sayHello");
    m2 = Class.forName("java.lang.Object").getMethod("toString");
    m0 = Class.forName("java.lang.Object").getMethod("hashCode");
    } catch (NoSuchMethodException var2) {
    throw new NoSuchMethodError(var2.getMessage());
    } catch (ClassNotFoundException var3) {
    throw new NoClassDefFoundError(var3.getMessage());
    }
    } 

    public $Proxy0(InvocationHandler var1) throws {
    super(var1);
    } 

    public final void sayHello() throws {
    try {
    super.h.invoke(this, m3, (Object[])null);
    } catch (RuntimeException | Error var2) {
    throw var2;
    } catch (Throwable var3) {
    throw new UndeclaredThrowableException(var3);
    }
    } 

    public final boolean equals(Object var1) throws {
    try {
    return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
    } catch (RuntimeException | Error var3) {
    throw var3;
    } catch (Throwable var4) {
    throw new UndeclaredThrowableException(var4);
    }
    }

    public final String toString() throws {
    try {
    return (String)super.h.invoke(this, m2, (Object[])null);
    } catch (RuntimeException | Error var2) {
    throw var2;
    } catch (Throwable var3) {
    throw new UndeclaredThrowableException(var3);
    }
    } 

    public final int hashCode() throws {
    try {
    return (Integer)super.h.invoke(this, m0, (Object[])null);
    } catch (RuntimeException | Error var2) {
    throw var2;
    } catch (Throwable var3) {
    throw new UndeclaredThrowableException(var3);
    }
    }

    } 

    iUser.sayHello() 实质上调用的是 $Proxy0.sayHello() 也就是

    public final void sayHello() throws {
    try {
    super.h.invoke(this, m3, (Object[])null);
    } catch (RuntimeException | Error var2) {
    throw var2;
    } catch (Throwable var3) {
    throw new UndeclaredThrowableException(var3);
    }
    }

    这里其实有一个面试题,问 JDK动态代理为什么是代理接口而不是类呢?public final class $Proxy0 extends Proxy implements IUser ,因为已经继承了 Proxy,而 Java 不能多继承。  

  • 相关阅读:
    Linux kill -9 和 kill -15 的区别
    redis 学习笔记之(五)redis-cli 命令
    专题(十四)awk
    Linux 学习笔记之(十一)SSH
    Linux 学习笔记之(十)查看文件
    rust 读写文件
    rust 显示本机ip
    rust error: linking with `link.exe` failed: exit code: 1181(未解决)
    Building a Concurrent Web Server with Async Rust
    Asynchronous Programming in Rust
  • 原文地址:https://www.cnblogs.com/xums/p/12651971.html
Copyright © 2011-2022 走看看