详解java动态代理的2种实现方式

 更新时间:2016年11月30日 09:54:05   作者:眺望小寒山  
目前Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。这篇文章主要介绍了详解java动态代理的2种实现方式 ,有兴趣的可以了解一下。

java的动态代理在接java的api上有说明,这里就不写了。我理解的代理:

对特定接口中特定方法的功能进行扩展,这就是代理。代理是通过代理实例关联的调用处理程序对象调用方法。

下面通过一个例子看一下:

接口:

public interface Num {
  void show();
  
  int getNum();
  
  int getProduct(int x);
}

实现类:

public class MyNum implements Num {
  @Override
  public int getNum() {
    return 3;
  }
  
  @Override
  public int getProduct(int x) {
    return x;
  }

  @Override
  public void show() {
    System.out.println("底层方法打印数字99");
  }
}

先看一下Method中的invoke方法在api中是怎么描述的

就是说调用处理程序对接口的实现类对象调用Method对象表示的底层方法。

第一种实现代理的方式:

public class NumProxy {
  private Object num;

  //通过构造方法构造接口的实现类对象
  public NumProxy(Object num) {
    this.num = num;
  }

  public Object getNumByProxy(){
    Object numProxy = Proxy.newProxyInstance(num.getClass().getClassLoader(), new Class[]{Num.class}, new InvocationHandler() {
      /**
       * method: 对应于在代理实例上调用的接口方法的 Method 实例。我理解的就是被代理的真实方法实例
       * args: 我理解的是真实方法的参数数组
       */
      @Override
      public Object invoke(Object proxy, Method method, Object[] args)
          throws Throwable {
        Object obj = null;
        System.out.println("在方法之前开始记录");
        String methodName = method.getName();
        if("getProduct".equals(methodName)){
          obj = method.invoke(num, args);
          obj = (Integer) obj * 2;
          System.out.println("proxy: getProduct()结束");
        }
        else if("show".equals(methodName)){
          obj = method.invoke(num, args);
          System.out.println("proxy: show()结束");
        }
        return obj;
      }
    });
    return numProxy;
  }
}

第二种实现代理的方式:通过实现InvocationHandler接口

public class NumProxyImpl implements InvocationHandler {
  //这里我把接口类型具体化了, 没有写成Object
  private Num num;
  
  public NumProxyImpl(Num num){
    this.num = num;
  }
  
  @Override
  public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
    Object obj = null;
    String methodName = method.getName();
    if("getProduct".equals(methodName)){
      System.out.println("proxy: getProduct()开始");
      obj = method.invoke(num, args);
      obj = (Integer) obj * 2;
      System.out.println("proxy: getProduct()结束");
    }else if("show".equals(methodName)){
      System.out.println("proxy: show()开始");
      obj = method.invoke(num, args);
      System.out.println("proxy: show()结束");
    }
    return obj;
  }
}

测试代码:

public class TestNum {
  public static void main(String[] args) {
    //两种方式一起测试
    NumProxy np = new NumProxy(new MyNum());
    Num numProxy = (Num) np.getNumByProxy();
    int x = numProxy.getProduct(2);
    System.out.println(x);
    numProxy.show();
    
    System.out.println("----------------");
    NumProxyImpl npi = new NumProxyImpl(new MyNum());
    Num numPro = (Num) Proxy.newProxyInstance(Num.class.getClassLoader(), new Class[]{Num.class}, npi);
    int n = numPro.getProduct(3);
    System.out.println(n);
    numPro.show();
  }
}

控制台结果:

第二种方式有点小疑惑,不知道大家有没有,那就是并没有显示的调用NumProxyImpl中的invoke方法,可是却执行了,嗯嗯,这个自己下去看一下啊

不想麻烦的只需要记住就行了。

比如编码的处理就可以用到代理,下次写个例子。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java RabbitMQ消息队列详解常见问题

    Java RabbitMQ消息队列详解常见问题

    消息队列是最古老的中间件之一,从系统之间有通信需求开始,就自然产生了消息队列。本文告诉什么是消息队列,为什么需要消息队列,常见的消息队列有哪些,RabbitMQ的部署和使用
    2022-07-07
  • JDK19新特性使用实例详解

    JDK19新特性使用实例详解

    这篇文章主要为大家介绍了JDK19新特性使用实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • JAVA如何使用Math类操作数据

    JAVA如何使用Math类操作数据

    这篇文章主要介绍了JAVA如何使用Math类操作数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Java SpringBoot集成ChatGPT实现AI聊天

    Java SpringBoot集成ChatGPT实现AI聊天

    ChatGPT已经组件放开了,现在都可以基于它写插件了,也许可以用它结合文字语音开发一个老人小孩需要的智能的说话陪伴啥的,这篇文章就介绍SpringBoot结合ChatGPT实现AI聊天感兴趣的同学可以借鉴一下
    2023-04-04
  • Java栈和基础队列的实现详解

    Java栈和基础队列的实现详解

    这篇文章主要介绍了Java数据结构中的栈与队列,在Java的时候,对于栈与队列的应用需要熟练的掌握,这样才能够确保Java学习时候能够有扎实的基础能力。本文小编就来详细说说Java中的栈与队列,需要的朋友可以参考一下
    2022-02-02
  • Spring MVC学习教程之RequestMappingHandlerAdapter详解

    Spring MVC学习教程之RequestMappingHandlerAdapter详解

    这篇文章主要给大家介绍了关于Spring MVC学习教程之RequestMappingHandlerAdapter的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-11-11
  • Spring Boot + Mybatis多数据源和动态数据源配置方法

    Spring Boot + Mybatis多数据源和动态数据源配置方法

    最近做项目遇到这样的应用场景,项目需要同时连接两个不同的数据库A, B,并且它们都为主从架构,一台写库,多台读库。下面小编给大家带来了Spring Boot + Mybatis多数据源和动态数据源配置方法,需要的朋友参考下吧
    2018-01-01
  • Spring使用RestTemplate模拟form提交示例

    Spring使用RestTemplate模拟form提交示例

    本篇文章主要介绍了Spring使用RestTemplate模拟form提交示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • 浅谈Java实现回溯算法之八皇后问题

    浅谈Java实现回溯算法之八皇后问题

    八皇后问题是一个古老而又著名的问题,是学习回溯算法的一个经典案例。今天我们就一起来探究一下吧
    2021-06-06
  • Spring中三种常见Bean的初始化参数机制你了解吗

    Spring中三种常见Bean的初始化参数机制你了解吗

    在Spring框架中,Bean的实例化与初始化是一个复杂的过程,本文我们主要来聊一聊它的常见的三种机制:InitializingBean接口、BeanDefinitionRegistryPostProcessor接口和EnvironmentAware接口,感兴趣的小伙伴可以了解下
    2023-11-11

最新评论