反射与动态代理简直是影视圈的神马组合

举报
周杰伦本人 发表于 2022/11/29 18:29:37 2022/11/29
【摘要】 反射与动态代理简直是影视圈的神马组合 反射 代理 静态代理 动态代理 总结 反射与动态代理简直是影视圈的神马组合Java可以在运行的时候知道对象的信息,这主要体现在Java的两个功能,RTTI和反射。 反射上篇文章我们讲了RTTI的一些特性,它可以确定运行时的对象类型,这个类是在编译的时候是确定的,这样才能通过编译后的Class文件来加载类对象。当我们在编译时无法获取类信息的时候,就可以考...

反射与动态代理简直是影视圈的神马组合

Java可以在运行的时候知道对象的信息,这主要体现在Java的两个功能,RTTI和反射。

反射

上篇文章我们讲了RTTI的一些特性,它可以确定运行时的对象类型,这个类是在编译的时候是确定的,这样才能通过编译后的Class文件来加载类对象。当我们在编译时无法获取类信息的时候,就可以考虑使用反射,既然本地没有Class文件,可能就是通过网络获取Class文件,这时候我们就可以使用反射来获取类信息。

JDK中有个java.lang.reflect反射包,里面定义了反射用到的一些类,

代理

反射往往与动态代理相结合使用,所谓代理就是自己由于各种各样的原因不好抛头露面,有一个代理类来帮它完成一件事情,代理类往往在真正方法执行的前后添加逻辑
下面我们举个代理模式使用的例子来说明一些

静态代理

定义一个接口:

interface Interface {
  void doSomething();
}

定义真正的对象:

class RealObject implements Interface {
  public void doSomething() { 
    System.out.println("简单输出"); 
  }
}

定义代理类:

class SimpleProxy implements Interface {
  private Interface proxied;
  public SimpleProxy(Interface proxied) {
    this.proxied = proxied;
  }
  public void doSomething() {
    System.out.println("使用代理类");
    proxied.doSomething();
  }
}  

使用:

new SimpleProxy(new RealObject()).doSomething();

这样我们看一下代码,,输出结果如下会先输出使用代理类 ,然后是简单输出

这是静态代理的实现,代理类需要我们定义,而动态代理就不一样了。

动态代理

动态代理可以动态创建代理并动态调用需要代理的方法。

定义动态代理类,这里我们使用实现InvocationHandler接口来,并重写他的invoke()方法

动态代理类:

class DynamicProxyHandler implements InvocationHandler {
  private Object proxied;
  public DynamicProxyHandler(Object proxied) {
    this.proxied = proxied;
  }
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("代理类: " + proxy.getClass() + ", 方法: " + method + ", 参数: " + args);
    if(args != null)
      for(Object arg : args)
        System.out.println("  " + arg);
    return method.invoke(proxied, args);
  }
}  

动态代理类的这一个invoke()方法的重写就够用了,当接口定义其他方法的时候,静态代理类需要同时实现接口的其他方法,而动态代理类就不需要了,这就是它的优势所在。

使用:

Interface proxy = (Interface)Proxy.newProxyInstance(
      Interface.class.getClassLoader(),
      new Class[]{ Interface.class },
      new DynamicProxyHandler(new RealObject()));
      
 proxy.doSomething();

运行结果:代理类:class $Proxy0, 方法:public abstract void Interface.doSomething(),参数: null

这里定义的动态代理类和静态代理类差不多,但比静态代理类稍微复杂一点。

我们使用Proxy.newProxyInstance()方法来创建动态代理对象,Method的invoke()方法调用被代理的对象的相应的方法,参数也可以携带。

总结

这篇文章我们讲了反射和代理的内容,往往他们两个结合起来使用,代理又分为静态代理和动态代理,动态代理相比静态代理更加灵活,减少代理类方法的编写,这也是我们生产中或者源码中经常用到的代理模式。动态代理的实现我们这里是使用了实现InvocationHandler接口的JDK代理方式,除此之外还可以使用CGlib代理。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。