Java动态代理Proxy&InvocationHandler 实例

代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数. 

话不多说, show you code . ...

 

1.定义代理的接口类.

public interface People {
    public String work();

}

2.定义接口的实现类.

import java.time.LocalDate;

public class Teacher implements People {
    @Override
    public String work() {
        System.out.println("上课=>"+ LocalDate.now() );
        return "上课";
    }
}

3.定义代理的实现类

这里最重要的是构造函数和 invoke方法.

构造函数: 设置要被代理的对象.

invoke: 根据请求的方法&参数 . 构造代理实现

 


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

public class WorkHandler implements InvocationHandler {
    //代理类中的真实对象
    private Object obj;

    public WorkHandler() {
        // TODO Auto-generated constructor stub
    }
    //构造函数,给我们的真实对象赋值
    public WorkHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("WorkHandler#invoke    "+proxy.getClass().getName());
        System.out.println("WorkHandler#invoke    "+this.obj.getClass().getName());

        //在真实的对象执行之前我们可以添加自己的操作
        System.out.println("before invoke。。。");
        Object invoke = method.invoke(obj, args);
        //在真实的对象执行之后我们可以添加自己的操作
        System.out.println("after invoke。。。");
        return invoke;
    }


}

 

4.定义运行方法


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

public class Client {

    public static void main(String[] args) {
        //要代理的真实对象
        People people = new Teacher();
        //代理对象的调用处理程序,我们将要代理的真实对象传入代理对象的调用处理的构造函数中,最终代理对象的调用处理程序会调用真实对象的方法
        InvocationHandler handler = new WorkHandler(people);
        /**
         * 通过Proxy类的newProxyInstance方法创建代理对象,我们来看下方法中的参数
         * 第一个参数:people.getClass().getClassLoader(),使用handler对象的classloader对象来加载我们的代理对象
         * 第二个参数:people.getClass().getInterfaces(),这里为代理类提供的接口是真实对象实现的接口,这样代理对象就能像真实对象一样调用接口中的所有方法
         * 第三个参数:handler,我们将代理对象关联到上面的InvocationHandler对象上
         */
        People proxy = (People) Proxy.newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);

        System.out.println(proxy.work());

        System.out.println("Client#manin "+proxy.getClass());

    }

}

5. 输出结果

WorkHandler#invoke    com.sun.proxy.$Proxy0
WorkHandler#invoke    org.apache.hadoop.reflect.Teacher
before invoke。。。
老师教书育人...
after invoke。。。
教书
Client#manin class com.sun.proxy.$Proxy0

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章