JDK 动态代理

动态代理机制 

Java 里面,动态代理是通过 Proxy.newProxyInstance()方法来实现的,它需要传入被动态代理的接口类
// 生成代理文件写入磁盘
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        ITradinPostService runService = (ITradinPostService) Proxy.newProxyInstance(ITradinPostService.class.getClassLoader(), new Class[]{ITradinPostService.class}, (proxy, method, args1) -> {
            System.out.println("动态代理");
            return "hello";
        });
        System.out.println(runService.run());

JDK 动态代理_第1张图片

JDK 动态代理的底层实现 

之所以要传入接口,不能传入类,还是取决于 JDK 动态代理的底层实现 JDK 动态代理会在程序运行期间动态生成一个代理类$Proxy0。
JDK 动态代理_第2张图片
这个动态生成的代理类 会继承 java.lang.reflect.Proxy 类,同时还会实现被代理类的接口 IHelloService。 在 Java 中,是不支持多重继承的。而每个动态代理类都会继承 Proxy 类(这也是 JDK 动态代理的实现规范),所以就导致 JDK 里面的动态代理只能代理接口,而不能代理 实现
public final class $Proxy0 extends Proxy implements ITradinPostService {
    // 省略
    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

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

}
Proxy 这个类只是保存了动态代理的处理器InvocationHandler,如果不抽出来,直接设置到$Proxy0 动态代理类里面,也是可以的。
  • 动态代理本身的使用场景或者需求,只是对原始实现的一个拦截,然后去做一些功能的增强或者扩展。而实际的开发模式也都是基于面向接口来开发,所以基于接口来实现动态代理,从需求和场景都是吻合的。当然确实可能存在有些类没有实现接口的,那这个时候,JDK 动态代理确实无法满足。
  • 在 Java 里面,类的继承关系的设计,更多的是考虑到共性能力的抽象,从而提高 代码的重用性和扩展性,而动态代理也是在做这样一个事情,它封装了动态代理类生成的抽象逻辑、判断一个类是否是动态代理类、InvocationHandler 的持有等等,那么把这些抽象的公共逻辑放在 Proxy 这个父类里面,很显然是一个比较正常的设计思路。

 

你可能感兴趣的:(java面试题,java,开发语言)