声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
* 下面的代码关注两种代理:
* 1.虚代理
* 2.保护代理
*/
//订单类接口
interface IOrder {
void setName(String name);
void setID(String id);
String getName();
String getID();
}
class Order implements IOrder {
private String id;
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getID() {
return this.id;
}
public void setID(String id) {
this.id = id;
}
}
class OrderProxy implements IOrder {
private Order order;
private boolean nameLoaded;
public OrderProxy(Order order) {
this.order = order;
this.nameLoaded = false;
}
/*
* 1、虚代理
* a. 客户查询订单信息时,只查询客户要求的信息:订单ID(假设这个查询比较快)
* b. 只有当用户要求更详细的信息(假设只是一个订单名称)时,才再次到数据库查询
* 这样做的原因是,通常查询“详细信息”时,会花费更多的时间和空间,有点“延迟加载”的感觉
*/
private void loadName() {
if (!nameLoaded) {
System.out.println("request name but no name, fetch it from database:");
String name = "aName"; //模拟数据库操作
order.setName(name);
this.nameLoaded = true;
}
}
public String getID() {
return order.getID();
}
/*
* 2.保护代理,可以在这里加上条件,符合则调用真实的order的方法。例如只有订单创建者能修改订单名称
*/
public void setName(String name) {
boolean canChangeName = true; //根据实际设置
if (canChangeName) {
order.setName(name);
System.out.println("Request accepted. Name changed.");
}
}
public void setID(String id) {
order.setID(id);
}
public String getName() {
if (!nameLoaded) {
this.loadName();
}
return this.order.getName();
}
}
public class ProxyPattern {
public static void main(String[] args) {
//1.静态代理
ProxyPattern p = new ProxyPattern();
IOrder order = p.getOrder();
System.out.println("id:" + order.getID());
//测试虚代理。如果“客户”没有调用getName,那“到数据库查询name”这个操作就可以不执行了
System.out.println("name:" + order.getName());
//测试保护代理
order.setName("newName");
System.out.println(order.getName());
//2.动态代理
//准备测试数据
Order order2 = new Order();
order2.setID("originalID");
order2.setName("originalName");
DynamicProxy dProxy = new DynamicProxy();
IOrder iOrder = dProxy.getProxyOrder(order2);
iOrder.setID("anotherID");
iOrder.setName("anotherName");
System.out.println(iOrder.getID() + ","+ iOrder.getName());
}
//模拟从数据库查询Order
public IOrder getOrder() {
//这里创建的是代理,而非真实的Order
//IOrder order = new Order();
OrderProxy proxy = new OrderProxy(new Order());
System.out.println("simple info. Only fetch order's id from database:");
String id = "aID"; //模拟从数据库取得ID
proxy.setID(id);
return proxy;
}
}
//=======================以上实现代理的方式称为静态代理===========================================
/**
* JDK里面的InvocationHandler来实现代理,称为动态代理
*/
class DynamicProxy implements InvocationHandler{
private IOrder order;
public IOrder getProxyOrder(Order order) {
this.order = order;
//把真正的订单对象和动态代理关联起来
IOrder iOrder = (IOrder) Proxy.newProxyInstance(order.getClass().getClassLoader(),
order.getClass().getInterfaces(),
this);
return iOrder;
}
public Object invoke(Object obj, Method method, Object[] aobj) throws Throwable {
Object result = null;
//假设不允许执行setID操作
if (method.getName().equalsIgnoreCase("setID")) {
System.out.println(method.getName() + ":Access denied.");
} else {
//result = method.invoke(obj, aobj); //不能这样写。要调用真实的order:
result = method.invoke(order, aobj);
}
return result;
}
}