代理对于我们并不陌生,在 QQ 群,微信群中,时不时会出现一两个人招代理,XX 代理,XX 代理,对于我们编程中其实也有代理,将原本属于自己的任务委托给别人去执行。我们来一探究竟。
定义:
为其他对象提供一种代理,以控制对这个对象的访问。
代理模式的通用类图:
- Subject 抽象主题角色:
抽象主题类可以是抽象类或者接口 - RealSubject 具体主题角色
被代理的角色。 - Proxy 代理主题角色
代理类。
优点:
- 职责清晰
例如例子中的RealSubject只关心具体的业务逻辑,而像before()、after()等逻辑就不需要它来操心。 - 高扩展性
应用场景
例如 Spring AOP,Struts 表单对象映射等。也像生活中的游戏代练,找律师打官司,微商代理等。
简单代理
简单代理通用代码:
Subject.java
public interface Subject {
void request();
}
RealSubject.java
public class RealSubject implements Subject {
public void request() {
System.out.println("someone request...");
}
}
Proxy.java
public class Proxy implements Subject {
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
public void request() {
this.subject.request();
}
}
客户端调用:
Client.java
public class Client {
public static void main(String[] args) {
Subject subject = new RealSubject();
Proxy proxy = new Proxy(subject);
proxy.request();
}
}
这是最简单的一个代理。
如果我们想要在调用 request() 之前或之后增加其他方法,那只要改写 Proxy 中的 request() 方法即可,如:
public class Proxy implements Subject {
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
public void request() {
before();
this.subject.request();
after();
}
}
动态代理
动态代理运用到反射机制。
动态代理在实现阶段并不关心代理谁,而在运行阶段才指定代理的是哪一个对象。
面向切面编程(AOP)的核心就是动态代理。
我们将上面的简单代理改为动态代理:
DynamicProxyIH.java
public class DynamicProxyIH implements InvocationHandler {
Object obj = null;
public DynamicProxyIH(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(this.obj, args);
}
}
实现 JDK 内置的 InvocationHandler 接口。该接口的 invoke 方法会完成对真实方法的调用。也就是说给定一个接口,动态代理会宣城已经实现了该接口的所有方法了。
更改后的客户端代码:
Client.java
public class Client {
public static void main(String[] args) {
Subject subject = new RealSubject();
Proxy proxy = new Proxy(subject);
proxy.request();
dynamicProxy();
}
public static void dynamicProxy() {
Subject subject = new RealSubject();
ClassLoader classLoader = subject.getClass().getClassLoader();
InvocationHandler dynamicProxyIH = new DynamicProxyIH(subject);
Subject dynamicSubject = (Subject) java.lang.reflect.Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, dynamicProxyIH);
dynamicSubject.request();
}
}
我们可以把上部分 Client 中的动态获取实例的代码抽出来,叫做 SubjectDynamicProxy,让它继承 DynamicProxy。
DynamicProxy.java
public class DynamicProxy {
public static T getInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler invocationHandler) {
return (T) java.lang.reflect.Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
SubjectDynamicProxy.java
public class SubjectDynamicProxy extends DynamicProxy {
public static T newInstance(Subject subject) {
ClassLoader classLoader = subject.getClass().getClassLoader();
Class[] classes = subject.getClass().getInterfaces();
InvocationHandler invocationHandler = new MyInvocationHandler(subject);
return getInstance(classLoader, classes, invocationHandler);
}
}
MyInvocationHandler.java
public class MyInvocationHandler implements InvocationHandler {
private Object object;
public MyInvocationHandler(Object object) {
this.object = object;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(object, args);
}
}
Client.java 增加方法
public static void commonDynamicProxy() {
Subject subject = new RealSubject();
Subject proxy = SubjectDynamicProxy.newInstance(subject);
proxy.request();
}
如上就是通用的动态代理方法。我们可以在 MyInvocationHandler 实现我们自己的逻辑处理。实现 AOP。
本文参考: 设计模式之禅
来个两毛钱砸死我啊,我也不想这么棒棒的啊! 赏
微信打赏
支付宝打赏

