1、实例
public class Main {
public static void main(String args[]) {
Subject realSubject = new RealSubject(); // 创建委托对象
ProxyHandler proxyHandler = new ProxyHandler(realSubject); // 创建 InvocationHandler 对象
Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader()
, realSubject.getClass().getInterfaces()
, proxyHandler); // 创建代理对象
proxy.request(); // 使用代理对象
}
}
/**
* 接口
*/
interface Subject {
public void request();
}
/**
* 让想要动态代理的类实现接口
*/
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("real request");
}
}
/**
* 一个 InvocationHandler 类
*/
class ProxyHandler implements InvocationHandler{
private Subject subject;
public ProxyHandler(Subject subject){
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) //proxy就是生成的代理对象
throws Throwable {
System.out.println("====before===="); //定义预处理的工作,当然你也可以根据 method的不同进行不同的预处理工作
Object result = method.invoke(subject, args);
System.out.println("====after====");
return result;
}
}
------------------------------输出---------------------------------------
====before====
real request
====after====
2、分析
- Proxy.newProxyInstance
ClassLoader:类加载器
Class<?>[]:【想要动态代理的类】实现的接口
InvocationHandler:动态代理对象的方法在执行时,会调用 InvocationHandler 里面的 invoke 方法去执行
- InvocationHandler 是 Java 提供的动态代理实现类,想要使用动态代理,必须实现该接口,重写invoke方法,并酌情在原方法的前边或后边插入需要的代码,method.invoke(target, args)会调用原方法(比如 RealSubject 类中的 request()方法)
- InvocationHandler.invoke(Object proxy, Method method, Object[] args) 参数分析:
proxy:反射创建的代理对象
method:代理对象调用的方法
args:调用的参数
- 当我们调用
proxy.request();
时,invoke 方法便会被调用。request 方法是自动生成的,内部实现如下
public final class $Proxy1 extends Proxy implements Subject{
private InvocationHandler h;
private $Proxy1(){}
public $Proxy1(InvocationHandler h){
this.h = h;
}
public int request(int i){
Method method = Subject.class.getMethod("request", new Class[]{int.class}); // 创建 method 对象
return (Integer)h.invoke(this, method, new Object[]{new Integer(i)}); // 调用了 invoke 方法
}
}
- 参考资料
https://www.jianshu.com/p/c15c4a45b1be
https://blog.csdn.net/u012326462/article/details/81293186