美文网首页
JDK动态代理

JDK动态代理

作者: 白马王朗 | 来源:发表于2018-01-25 12:43 被阅读0次

RPC框架中,我们直接调用别人提供的接口,就执行InnovationHandler中invoke方法实现方法的远程调用逻辑。这是大家所熟知的,但是InnovationHandler的invoke方法被谁调用?什么时候调用?接下来我们用jdk动态代理来一探究竟:
接口:

interface IUser {
    public String sayHello(String hello) ;
}

实现:

class UserImpl implements IUser{

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

测试类

class TestProxy{
    public static void main(String[] args) {
        //让jvm生成的代理类保存到本地       
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        System.out.println(Proxy.getProxyClass(IUser.class.getClassLoader(), IUser.class));

        UserImpl user = new UserImpl();
        IUser userProxy = (IUser)Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理类开始工作");
                //如果是RPC框架,这里会启动序列化方案,以及通信调用数据;
                return method.invoke(proxy, args);
            }
        });
        userProxy.sayHello("hello");
    }
}

生成代理对象:

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

public final class $Proxy0 extends Proxy implements IUser {
    private static Method m1;
    private static Method m3;
    private static Method m0;
    private static Method m2;

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

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

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

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

    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);
        }
    }

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

真相大白:可以看到生成代理类中sayHello方法如下:

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

至此,我们找到是代理类自己调用了成员invocationHandler的invoke方法,从而实现了方法的调用。

相关文章

网友评论

      本文标题:JDK动态代理

      本文链接:https://www.haomeiwen.com/subject/aecvaxtx.html