版权声明:本文为博主原创,未经博主允许不得转载。 https://blog.csdn.net/weixin_36904568/article/details/90041182
1. 定义
为另一个对象提供一个代理对象,控制对这个对象的访问
2. 分类
- 远程代理(另一个JVM的对象)
- 虚拟代理(开销大的对象)
- 保护代理(不安全的对象)
- 缓存代理(减小开销)
- 同步代理(多线程的安全访问)
- 防火墙代理(保护网络资源)
- 智能引用代理(引用某个对象时的处理)
- 复杂隐藏代理
- 写入时复制代理
3. 使用
- 抽象对象:声明了目标对象和代理对象的共同接口,定义抽象的业务
- 真正对象:被代理和被控制访问的对象,实现具体的业务
- 代理对象:持有真正对象的引用,创建和销毁真正的对象、控制真正的对象
(1)远程代理
代理作为另一个JVM对象的本地代表,利用网络转发请求,在调用远程方法时作为替身
- 服务器
- 抽象对象
- 真正对象
- RMI代理对象
- 客户辅助对象stub:打包调用信息,转发请求
- 服务辅助对象skeleton:解开包,接收请求,调用方法,返回结果
- 客户端:调用代理对象的方法
服务端:
- 定义抽象接口:定义业务方法(继承Remote、变量和返回值使用原语或序列化的类)
- 定义真正对象:实现业务方法(继承UnicastRemoteObject、构造器)、注册registry
- 产生代理对象:利用RMIC产生stub、skeleton
- 启动RMI registry:记录客户代理
- 远程服务
客户端:
- 获取代理对象stub:通过抽象接口,在服务器的registry寻找具体代理对象,返回stub
- 使用代理对象stub
(2)虚拟代理
代理作为创建开销大的对象的代表,在需要使用时才创建真正对象。在创建前和创建中都是由虚拟代理作为替身
- 抽象对象:抽象的业务
- 真正对象:实现业务方法
- 代理对象:如果真正对象创建好了,则委托请求。否则开始新的线程创建真正对象,先提供默认实现
- 客户端:调用抽象的业务方法
业务
package ProxyPattern;
/**
* 抽象接口
*/
public interface Subject {
public void operate();
}
package ProxyPattern;
/**
* 真正对象
*/
public class RealSubject implements Subject {
@Override
public void operate() {
System.out.println("真正的业务实现");
}
}
代理
package ProxyPattern;
/**
* 代理
*/
public class Proxy implements Subject{
private RealSubject realSubject;
@Override
public void operate() {
if (realSubject == null) {
new Thread(){
public void run(){
realSubject = new RealSubject();
System.out.println("创建完成");
realSubject.operate();
}
}.start();
System.out.println("业务的默认实现");
}
else
realSubject.operate();
}
}
测试
package ProxyPattern;
public class Test {
public static void main(String[] args) {
Subject subject = new Proxy();
System.out.println("首次调用");
subject.operate();
// System.out.println("第二次调用");
// subject.operate();
}
}
(3)保护代理
使用JAVA的动态代理,根据访问权限,决定用户能否访问对象的代理
- 抽象对象:抽象的业务
- 真正对象:实现具体的业务
- 代理对象:持有真正对象的引用,控制真正的对象
- 实际代理对象:代理收到方法后,请求实际工作的对象
- 抽象对象
- invoke(代理,方法名,参数) :判断方法能否执行
- 客户端:根据真正对象获取其对应的代理对象
- 创建代理+类加载器+代理实现接口+实际代理对象
业务
package ProxyPattern.ProtectProxy;
/**
* 抽象接口
*/
public interface Subject {
public void operateA();
public void operateB();
}
package ProxyPattern.ProtectProxy;
/**
* 真正对象
*/
public class RealSubject implements Subject {
@Override
public void operateA() {
System.out.println("真正的业务实现A");
}
@Override
public void operateB() {
System.out.println("真正的业务实现B");
}
}
代理对不同实体对象的具体处理过程
package ProxyPattern.ProtectProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 真正的代理处理过程
*/
public class MyInvocationHandler implements InvocationHandler {
private Subject subject;
public MyInvocationHandler(Subject subject){
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//对于实体RealSubject进行以下限制:
//对B结尾的方法进行保护,抛出异常
//对A结尾的方法正常访问
try {
if (method.getName().endsWith("A"))
return method.invoke(subject,args);
if (method.getName().endsWith("B"))
throw new Exception();
}
catch (Exception e){
System.out.println("无法操作B有关的方法");
}
return null;
}
}
测试
package ProxyPattern.ProtectProxy;
public class Test {
public static void main(String[] args) {
Subject subject = new RealSubject();
Subject proxy = getProxy(subject);
proxy.operateA();
proxy.operateB();
}
//根据业务的类和接口以及自己实现的处理过程,获取代理
static Subject getProxy(Subject subject){
return (Subject) java.lang.reflect.Proxy.newProxyInstance(
subject.getClass().getClassLoader(),
subject.getClass().getInterfaces(),
new MyInvocationHandler(subject)
);
}
}