-
意图
为其他对象提供一种代理以控制对这个对象的访问 -
别名:
Surrogate -
动机:
-
适用性:
a. 远程代理(Remote Proxy)为一个对象在不同的地址空间提供局部代表。
b. 虚代理(Virtual Proxy)根据需要创建开销很大的对象。
c. 保护代理(Protection Proxy)控制对原始对象的访问。
d. 只能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。 -
结构:
这是运行时刻一种可能的代理结构的对象图
-
参与者:
a. Proxy:
保存一个应用使得代理可以访问实体。
提供一个与Subject的接口相同的接口,这样代理就可以用来代替实体。
控制对实体的存取,并可能负责创建和删除它。
其他功能依赖于代理的类型:
1)Remote Proxy负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求。
2)Virtual Proxy可以缓存实体的附加信息,以便延迟对它的访问。
3)Protection Proxy检查调用这是否具有实现一个请求所必须的访问权限。
b. Subject:
定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。
c. RealSubject:
定义Proxy所代表的实体。 -
协作:
代理根据其种类,在适当的时候向RealSubject转发请求。 -
效果:
Proxy模式在访问对象时引入了一定程度的间接性。 -
实现:
-
代码示例:
public interface Subject {
void request();
}
public class Proxy implements Subject{
Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
System.out.println("Proxy request");
subject.request();
}
}
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("Real Subject request");
}
}
public class Client {
public static void main(String[] args) {
Proxy proxy = new Proxy(new RealSubject());
proxy.request();
}
}
/**
* 以下为Java中两种动态代理的方式 JDK动态代理 CGLib动态代理
*/
/**
* JDK动态代理
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* JDK动态代理是Java内置的动态代理工具,动态代理类需要实现InvocationHandler接口,并实现invoke方法。
*/
public class SubjectInvocationHandler implements InvocationHandler {
private Object targetObject;
public SubjectInvocationHandler(Object targetObject) {
this.targetObject = targetObject;
}
/**
*
* @param proxy 被代理对象
* @param method 被代理方法
* @param args 被代理方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(targetObject, args);
System.out.println("This is SubjectInvocationHandler invoke()");
return proxy;
}
}
/**
* JDKProxy构造类
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
@SuppressWarnings("all")
public class JDKProxy {
//通过Proxy类的newProxyInstance()方法创建代理类
public static <T> T getProxyInstance(T object, InvocationHandler handler) {
return (T) Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), handler);
}
}
//客户端调用
public class Client {
public static void main(String[] args) {
Subject subject = new RealSubject();
SubjectInvocationHandler subjectInvocationHandler = new SubjectInvocationHandler(subject);
Subject proxyInstance = JDKProxy.getProxyInstance(subject, subjectInvocationHandler);
proxyInstance.request();
}
}
/**
* CGLib动态代理
* 需要引入
* <dependency>
* <groupId>cglib</groupId>
* <artifactId>cglib</artifactId>
* <version>3.3.0</version>
* </dependency>
*/
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* CGLIB动态代理,需要实现MethodInterceptor,并实现intercept()
*/
public class SubjectMethodInterceptor implements MethodInterceptor {
/**
*
* @param o 被代理对象
* @param method 被代理方法
* @param args 被代理方法参数
* @param methodProxy 被代理方法的代理对象
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object methodPxy = methodProxy.invokeSuper(o, args);
System.out.println("This is SubjectMethodInterceptor intercept()");
return methodPxy;
}
}
/**
* CGLibProxy构造类
*/
public class CGLibProxy {
public static <T> T getProxyInstance(T object, MethodInterceptor methodInterceptor) {
return (T) Enhancer.create(object.getClass(), methodInterceptor);
}
}
//客户端调用
public class Client {
public static void main(String[] args) {
Subject subject = new RealSubject();
SubjectMethodInterceptor subjectMethodInterceptor = new SubjectMethodInterceptor();
Subject proxyInstance = CGLibProxy.getProxyInstance(subject, subjectMethodInterceptor);
proxyInstance.request();
}
}
-
已知应用:
-
相关模式:
Adapter:适配器Adapter为它所适配的对象提供了一个不同的接口。
Decorator:尽管decorator的实现部分与代理相似,当decorator的目的不一样。Decorator为对象添加一个或多个功能,而代理则控制对对象的访问。