代理模式是指通过一个代理类,用非侵入的方式为主业务逻辑增加额外功能。
普通代理
业务逻辑
// 请求接口
public interface IRequest {
void request();
}
// 真实业务逻辑
public class Request implements IRequest {
public void request() {
// 真实的请求处理逻辑
System.out.println("real request logic");
}
}
额外功能
public class OtherJob {
public static void before(){
System.out.println("do something before");
}
public static void after(){
System.out.println("do something after");
}
}
代理类
public class RequestProxy implements IRequest {
// 主业务逻辑类
private IRequest request;
public Proxy(IRequest request) {
this.request = request;
}
public void request() {
OtherJob.before();
this.request.request();
OtherJob.after();
}
}
- 代理类也实现了
IRequest
接口 - 代理类通过
before
和after
方法,增加了类的功能
场景类:
public class Client {
public static void main(String[] args) {
RequestProxy proxy = new RequestProxy(new Request());
proxy.request();
}
}
可以看到,实际上是通过 RequestProxy
代理类调用的逻辑。
运行结果
do something before
real request logic
do something after
动态代理
JDK 通过 Proxy
和 InvocationHandler
提供了动态代理的功能。
所谓动态代理,即不用我们去开发代理类(如上面的 RequestProxy
),而是 JAVA 代码在运行时帮我们产生代理类。
上面的 IRequest
、 Request
、 OtherJob
类保持不变。
handler 类
定义 RequestHandler
类,实现 InvocationHandler
接口。
public class RequestHandler implements InvocationHandler {
// 被代理类实例
private Object target;
public RequestHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 额外逻辑
OtherJob.before();
// 执行实际业务逻辑,即 Request.request 方法
Object obj = method.invoke(target, args);
// 额外逻辑
OtherJob.after();
return obj;
}
}
场景类
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
IRequest request = new Request();
RequestHandler handler = new RequestHandler(request);
IRequest proxy = (IRequest) Proxy.newProxyInstance(
request.getClass().getClassLoader(),
request.getClass().getInterfaces(),
handler
);
proxy.request();
}
}
运行结果与上面的一致
do something before
real request logic
do something after
JAVA 的动态代理类有个限制,那就是被代理类必须要实现个接口。如果想代理没有实现接口的类,必须通过第三方包,如 CGLIB 库