代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在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