动态代理,InvocationHandler的invok为什么能调用到接口实现类方法

首先要加两点总容易疑惑的解答:

第一,newProxyInstance生成的并不是代理接口类 而是代理接口的实现类!!!

第二,动态代理本质是Proxy生成$Proxy0并代理了InvocationHandler!!!!

1.通过newProxyInstance方法中通过代理类lodar和接口实现instance生成$Proxy0类

(这个类实现了代理接口以及拥有代理所有接口的方法,并且可以传入多实现的实现类,但无法拥有继承类的实现接口方法,即使重写了父类接口的实现)

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 
{     
      ... 
      ... 
Class<?> cl = getProxyClass0(loader, intfs);//此处生成并返回一个$Proxy0类 
      ... 
      ... 
}

2.将代理对象的实现传入$Proxy0构造方法,接着$Proxy0调用父类Proxy的构造器,为父类属性赋值(属性为InvocationHandler类型)

protected InvocationHandler h; //InvocationHandler类型的属性
protected Proxy(InvocationHandler h) { 
    Objects.requireNonNull(h);
    this.h = h;
}
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException
{
    ...
    ...
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
    AccessController.doPrivileged(new PrivilegedAction<Void>() {
        public Void run() {
            cons.setAccessible(true);
            return null;
        }
    });
}
return cons.newInstance(new Object[]{h});
    ...
    ...
}

3.newProxyInstance返回一个$Proxy0类型的参数,再强制转换成代理接口类型

4.调用方法时直接调用$Proxy0中的方法,也就是调用父类Proxy中的h.invoke

public final class $Proxy0 extends Proxy implements TestInterface2 {
    ...
    ...
    public final void say() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    ...
    ...
}

最后思考一个问题:

当代理接口有多实现时他会调用哪个实现的接口呢?

看完之后就很好理解了,调用$Proxy0.invoke时只会调用到父类Proxy的属性InvocationHandler,而这个InvocationHandler就是你的InvocationHandler实现类,而这个实现类的target就是在你newProxyInstance时传入的那个接口实现类。

最最后再思考一下:

如果代理了多接口呢?如果有同时继承了其他接口的实现类呢?

感兴趣的可以试试,答案就是可以代理多接口,newProxyInstance的参数是一个Class<?>[] interfaces,但是代理到继承类的其他接口

ps:newProxyInstance只接受接口参数类型

if (!interfaceClass.isInterface()) {
    throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");
}

实现远程调用动态代理接口方法如下: 1. 创建一个接口,其中定义需要远程调用方法。 2. 创建一个远程调用实现,该实现接口中定义的方法。 3. 创建一个动态代理,该实现接口,并在方法执行时调用远程调用实现的对应方法。 4. 在客户端程序中,使用动态代理的实例来调用接口中的方法,实际上是调用了远程调用实现方法。 下面是一个实现远程调用动态代理接口的示例代码: ```java // 接口 public interface RemoteInterface { void remoteMethod(); } // 远程调用实现 public class RemoteImpl implements RemoteInterface { @Override public void remoteMethod() { // 远程调用实现 } } // 动态代理 public class RemoteProxy implements InvocationHandler { private Object target; public RemoteProxy(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 远程调用实现方法 method.invoke(target, args); return null; } } // 客户端程序 public class Client { public static void main(String[] args) { RemoteImpl remoteImpl = new RemoteImpl(); RemoteInterface remoteInterface = (RemoteInterface) Proxy.newProxyInstance( RemoteImpl.class.getClassLoader(), RemoteImpl.class.getInterfaces(), new RemoteProxy(remoteImpl) ); remoteInterface.remoteMethod(); } } ``` 在上面的示例代码中,我们定义了一个接口 RemoteInterface,并在 RemoteImpl 实现了该接口中的方法。然后,我们创建了一个动态代理 RemoteProxy,该实现InvocationHandler 接口,并在 invoke 方法调用了远程调用实现 RemoteImpl 中对应的方法。最后,在客户端程序中,我们使用 Proxy.newProxyInstance 方法创建了动态代理的实例,并调用接口中的方法,实际上是调用了远程调用实现方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值