首页 > 代码库 > 代理模式
代理模式
代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理(Proxy)。
代理就是一个Java对象代表另一个Java对象来采取行动。如:
public class ImageProxy implements Image {
//组合一个image实例,作为被代理的对象
private Image image;
//使用抽象实体来初始化代理对象
public ImageProxy(Image image) {
this.image = image;
}
/** * 重写Image接口的show()方法
* 该方法用于控制对被代理对象的访问,
* 并根据需要负责创建和删除被代理对象
*/
public void show()
{
//只有当真正需要调用image的show方法时才创建被代理对象
if(image==null)
{
image=newBigImage();
}
image.show();
}
}
调用时,先不创建:
Imageimage=newImageProxy(null);
Hibernate默认启用延迟加载,当系统加载A实体时,A实体关联的B实体并未被加载出来,A实体所关联的B实体全部是代理对象——只有
等到A实体真正需要访问B实体时,系统才会去数据库里抓取B实体所对应的记录。
借助于Java提供的Proxy和InvocationHandler,可以实现在运行时生成动态代理的功能,而动态代理对象就可以作为目标对象使用,而
且增强了目标对象的功能。如:
Panther
publicinterfacePanther{
//info方法声明
publicvoidinfo();
//run方法声明
publicvoidrun();
}
publicclassGunPantherimplementsPanther{
//info方法实现,仅仅打印一个字符串
publicvoidinfo()
{
System.out.println("我是一只猎豹!");
}
//run方法实现,仅仅打印一个字符串
publicvoidrun()
{
System.out.println("我奔跑迅速");
}
}
创建代理对象
public class MyProxyFactory{
//为指定target生成动态代理对象
publicstaticObjectgetProxy(Objecttarget)throwsException
{
//创建一个MyInvokationHandler对象
MyInvokationHandlerhandler=new MyInvokationHandler();
//为MyInvokationHandler设置target对象
handler.setTarget(target);
//创建、并返回一个动态代理
returnProxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);
}
}
增强代理的功能
public class MyInvokationHandler implements InvocationHandler {
//需要被代理的对象
private Object target;
public void setTarget(Object target)
{
this.target = target;
}
//执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Exception
{
TxUtil tx = new TxUtil();
//执行TxUtil对象中的beginTx。
tx.beginTx();
//以target作为主调来执行method方法
Object result = method.invoke(target , args);
//执行TxUtil对象中的endTx。
tx.endTx();
return result;
}
}
TxUtil
public class TxUtil {
//第一个拦截器方法:模拟事务开始
public void beginTx()
{
System.out.println("=====模拟开始事务=====");
}
//第二个拦截器方法:模拟事务结束
public void endTx()
{
System.out.println("=====模拟结束事务=====");
}
}
测试
public static void main(String[] args) throws Exception
{
//创建一个原始的GunDog对象,作为target
Panther target = new GunPanther();
//以指定的target来创建动态代理
Panther panther = (Panther)MyProxyFactory.getProxy(target);
//调用代理对象的info()和run()方法
panther.info();
panther.run();
}
Spring所创建的AOP代理就是这种动态代理。但是Spring AOP更灵活。