一文带你弄懂 Java 动态代理


一文带你弄懂 Java 动态代理

文章插图
作者 | mjzuo
责编 | 王晓曼
出品 | CSDN 博客
在说动态代理之前,先来简单看下代理模式 。
代理是最基本的设计模式之一 。它能够插入一个用来替代“实际”对象的“代理”对象,来提供额外的或不同的操作 。这些操作通常涉及与“实际”对象的通信,因此“代理”对象通常充当着中间人的角色 。
一文带你弄懂 Java 动态代理

文章插图
代理模式
代理对象为“实际”对象提供一个替身或占位符以控制对这个“实际”对象的访问 。被代理的对象可以是远程的对象,创建开销大的对象或需要安全控制的对象 。来看下类图:
一文带你弄懂 Java 动态代理

文章插图
再来看下类图对应代码,这是 IObject 接口,真实对象 RealObj 和代理对象 ObjProxy 都实现此接口:
 /**
* 为实际对象Tested和代理对象TestedProxy提供对外接口
*/
public interface IObject {
void request;
}
RealObj 是实际处理 request 逻辑的对象,但是出于设计的考量,需要对RealObj内部的方法调用进行控制访问 。
 public class RealObject implements IObject {
@Override
public void request {
// 模拟一些操作
}
}
ObjProxy 是 RealObj 的代理类,其同样实现了 IObject 接口,所以具有相同的对外方法 。客户端与 RealObj 的所有交互,都必须通过 ObjProxy 。
 public class ObjProxy implements IObject {
IObject realT;
public ObjProxy(IObject t) {
realT = t;
}
@Override
public void request {
if (isAllow)
realT.request;
}
/**
* 模拟针对请求的校验判断
*/
private boolean isAllow {
return true;
}
}
一文带你弄懂 Java 动态代理

文章插图
番外
代理模式和装饰者模式不管是在类图,还是在代码实现上,几乎是一样的,但我们为何还要进行划分呢?其实学设计模式,不能拘泥于格式,不能死记形式,重要的是要理解模式背后的意图,意图只有一个,但实现的形式却可能多种多样 。这也就是为何那么多变体依然属于xx设计模式的原因 。
代理模式的意图是替代真正的对象以实现访问控制,而装饰者模式的意图是为对象加入额外的行为 。
一文带你弄懂 Java 动态代理

文章插图
动态代理
JAVA 的动态代理可以动态的创建代理并动态的处理所代理方法的调用,在动态代理上所做的所以调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的策略 。类图见下:
一文带你弄懂 Java 动态代理

文章插图
还以上面的代码为例,这是对外的接口 IObject:
 public interface IObject {
void request;
}
这是 InvocationHandler 的实现类,类图中 Proxy 的方法调用都会被系统传入此类,即 invoke 方法,而 ObjProxyHandler 又持有着 RealObject 实例,所以 ObjProxyHandler 是“真正”对 RealObject 对象进行访问控制的代理类 。
 public class ObjProxyHandler implements InvocationHandler {
IObject realT;
public ObjProxyHandler(IObject t) {
realT = t;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// request方法时,进行校验
if (method.getName.equals("request") && !isAllow)
return ;
return method.invoke(realT, args);
}
/**
* 模拟针对请求的校验判断
*/
private boolean isAllow {
return false;
}
}
RealObj 是实际处理 request 逻辑的对象 。
 public class RealObject implements IObject {
@Override
public void request {
// 模拟一些操作
}
}
动态代理的使用方法如下:我们通过 Proxy.newProxyInstance 静态方法来创建代理,其参数如下,一个类加载器、一个代理实现的接口列表、一个 InvocationHandler 的接口实现 。
 public void startTest {
IObject proxy = (IObject) Proxy.newProxyInstance(
IObject.class.getClassLoader,
new Class{IObject.class},
new ObjProxyHandler(new RealObject));
proxy.request; // ObjProxyHandler的invoke方法会被调用
}
一文带你弄懂 Java 动态代理


推荐阅读