java动态代理详解

什么是代理

  • 利用代理我们可以在运行时创建一个实现了一组给定接口的新类。
  • 这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用。

何时使用代理

  • 代理类可以在运行时创建全新的类,这样的代理类能够实现指定的接口。
  • 我们不能再运行时定义这些方法的新代码,而要提供一个调用处理器,即一个实现了InvocationHandler接口的类对象。

创建代理对象

无论何时用proxy调用某个方法,这个方法的名字和参数就会打印出来,之后再真正调用这个方法。
class TraceHandler implements InvocationHandler{
    private Object target;
    public TraceHandler(Object t)
    {
        target = t;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.print(target);
        //print会自动调用toString方法
        System.out.print("." + method.getName() +"(");
        if(args != null){
            for(int i = 0; i < args.length; i++){
                System.out.print(args[i]);
            if(i < args.length - 1)System.out.print(",");
            }
        }
        System.out.println(")");
        return method.invoke(target,args);
    }
}

Object invoke(Object obj, args)

调用包装在当前Method对象中的方法
obj:实例化后的对象。
args:用于方法调用的参数。

使用代理对象对二分法查找进行跟踪

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler)
loader:类加载器,为null会使用默认的类加载器。

interfaces:

 - interfaces数组中所有的对象必须表示接口,不能是类或者基本类型

 - interfaces数组中不能有两个元素可以引用相同的类对象

handler:即我们刚刚实现了InvocationHandler接口的类

public class Main {

    public static void main(String[] args) {
	// write your code here
 Object[] elements = new Object[1000];
 for(int i = 0;i < elements.length;i++){
     int value = i + 1;
     InvocationHandler handler = new TraceHandler(value);
     //每一个类都有一个隐含的静态成员class
     Object proxy = Proxy.newProxyInstance(null,new Class[]{Comparable.class},handler);
     elements[i] = proxy;
 }
 Integer key = new Random().nextInt(elements.length) + 1;
 //binarySearch中调用了compareTo方法
 int result = Arrays.binarySearch(elements,key);
 if(result >= 0 ) System.out.println(elements[result]);
    }
}

Integer类实现了Comparable接口,在binarySearch中会调用到Compara接口中的compareTo()方法。

为什么toString方法不属于Comparable接口也被代理——因为所有的代理类都覆盖了Object中的方法toString,equals和hashCode

在这里插入图片描述

  • 所有的代理类都拓展与Proxy类
  • 对于特定的类加载器和预设的一组接口来说,只能有一个代理类。
  • 代理类一定是public或final
  • 没有定义代理类的名字,JVM中的Proxy类将生成一个以字符串$Proxy开头的雷鸣
  • 代理类是指在运行过程中创建的,一旦被创建就成为了常规类。
  • 无论何时调用代理对象的方法,调用处理器(handler)的invoke方法都会被调用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值