Java中InvocationHandler接口中第一个参数proxy详解

上一篇文章我们详细的讲解了创建代理类的调用处理程序(实现InvocationHandler接口的类),获得代理对象的Proxy类,但是就发现InvocationHandler中的invoke方法中的第一个参数proxy好像从来没有用过,所以就开始在网上查询proxy的用途,最后在国外的网站上找到了不错的讲解stackoverflow.com,下面就根据自己的学习心得,讲解一下proxy。

1.讲解前我们先列一下我们要说明的问题
  • proxy代表什么意思
  • proxy参数怎么用及什么时候用
  • proxy参数运行时的类型是什么
  • 为什么不用this代替proxy
2.proxy代表什么意思

proxy是真实对象的真实代理对象,invoke方法可以返回调用代理对象方法的返回结果,也可以返回对象的真实代理对象(com.sun.proxy.$Proxy0)。

3.proxy参数怎么用及什么时候用

proxy参数是invoke方法的第一个参数,通常情况下我们都是返回真实对象方法的返回结果,但是我们也可以将proxy返回,proxy是真实对象的真实代理对象,我们可以通过这个返回对象对真实的对象做各种各样的操作。

  • 创建一个接口People,包含一个work方法,方法的返回对象是它本身
package com.test.Application;

public interface People {

    public People work(String workName);
    public String time();
}
  • 创建一个接口People的实现类Student
package com.test.Application;

public class Student implements People{

    @Override
    public People work(String workName) {
        System.out.println("工作内容是"+workName);
        return this;
    }
    @Override
    public String time() {
        return "2018-06-12";
    }
}
  • 创建一个代理类的调用处理程序WorkHandler
package com.test.Application;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class WorkHandler implements InvocationHandler{

    private Object obj;

    public WorkHandler(Object obj) {
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before 动态代理...");
        System.out.println(proxy.getClass().getName());
        System.out.println(this.obj.getClass().getName());
        if(method.getName().equals("work")) {
            method.invoke(this.obj, args);
            System.out.println("after 动态代理...");
            return proxy;
        } else {
            System.out.println("after 动态代理...");
            return method.invoke(this.obj, args);
        }
    }

}

我们可以看到上面的代理类调用处理程序打印了proxy参数对象,并且返回了proxy对象。

  • 客户端实例创建代理对象并输出结果
package com.test.Application;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {

    public static void main(String[] args) {
        People people = new Student();
        InvocationHandler handler = new WorkHandler(people);

        People proxy = (People)Proxy.newProxyInstance(people.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);
        People p = proxy.work("写代码").work("开会").work("上课");

        System.out.println("打印返回的对象");
        System.out.println(p.getClass());

        String time = proxy.time();
        System.out.println(time);
    }
}

运行结果:

after 动态代理...
before 动态代理...
com.sun.proxy.$Proxy0
com.test.Application.Student
工作内容是上课
after 动态代理...
打印返回的对象
class com.sun.proxy.$Proxy0

class com.sun.proxy.$Proxy0
before 动态代理...
com.sun.proxy.$Proxy0
com.test.Application.Student
after 动态代理...
2018-06-12

我们可以看到WorkHandler代理调用处理程序打印proxy参数输出的结果是com.sun.proxy.$Proxy0,这也说明proxy参数是代理类的真实代理对象;Proxy类生成的代理对象可以调用work方法并且返回真实的代理对象,也可以通过反射来对真实的代理对象进行操作。

4.proxy参数运行时的类型是什么

上面我们已经打印出了proxy的类型是:com.sun.proxy.$Proxy0真实的代理对象

5.为什么不用this替代

因为this代表的是InvocationHandler接口实现类本身,并不是真实的代理对象。

猜你喜欢

转载自blog.csdn.net/yaomingyang/article/details/81040390