Java中的代理模式
代理模式在Java Web的框架中经常使用到。比如说在对数据库的访问中,核心功能是对数据库的增删改查,而连接数据库、处理事务等功能我们在开发中也要考虑到。所以我们将数据库的CRUD抽象到接口中,然后实现该接口。 而将数据库连接、事务处理等功能交给代理类去完成。
上图描述了代理模式的基本框架。代理模式的核心是以下几点:
1. 代理实现类和真实的实现类都实现了接口
2. 代理实现类必须持有一个真实实现类的引用
3. 代理实现类完成非核心功能,而核心功能有其持有的真是实现类完成
现在以对数据库访问为例。加入数据库中有Dept表(只有表示部门名称和地点的dname、loc字段),Java类如下:
package other; import java.io.Serializable;
import java.util.Date; @SuppressWarnings("serial")
public class Dept implements Serializable
{
private String dname;
private String loc;
public String getDname()
{
return dname;
}
public void setDname(String dname)
{
this.dname = dname;
}
public String getLoc()
{
return loc;
}
public void setLoc(String loc)
{
this.loc = loc;
}
}
对数据库的访问有一个IDAO<K,V>接口,为了演示方便,只包含了数据增加和数据修改功能:
package other; public interface IDAO<K,V>
{
public boolean doCreate(V vo) throws Exception ;
public boolean doUpdate(V vo) throws Exception ;
}
下面是对IDAO<K,V>的实现,该类用伪代码实现:
package other; public class DAOImpl implements IDAO<Integer, Dept>
{ @Override
public boolean doCreate(Dept vo) throws Exception
{
System.out.println("===成功创建Dept记录===");
return true;
} @Override
public boolean doUpdate(Dept vo) throws Exception
{
System.out.println("===成功更新Dept记录===");
return true;
}
}
下面定义的是代理类,代理类持有一个对DAOImpl的引用。代理类要完成数据库自动提交设置,同时还要调用真实类完成对数据库的访问:
package other; public class DAOImplProxy implements IDAO<Integer, Dept>
{
private IDAO<Integer, Dept> realObject = null;
public DAOImplProxy(IDAO<Integer, Dept> realObject)
{
this.realObject = realObject;
} private void updatePre()
{
System.out.println("===取消自动提交===");
} private void updateAfter()
{
System.out.println("===设置自动提交===");
} private void roolBack()
{
System.out.println("===事务出现异常,回滚===");
} @Override
public boolean doCreate(Dept vo) throws Exception
{
try
{
this.updatePre();
boolean retVal = this.realObject.doCreate(vo);
this.updateAfter();
return retVal;
}catch(Exception e)
{
this.roolBack();
e.printStackTrace();
throw e;
}
}
@Override
public boolean doUpdate(Dept vo) throws Exception
{
try
{
this.updatePre();
boolean retVal = this.realObject.doUpdate(vo);
this.updateAfter();
return retVal;
}catch(Exception e)
{
this.roolBack();
e.printStackTrace();
throw e;
}
} }
可以看到,代理类也实现了IDAO<K,V>接口,而对Dept表的插入和更新之前和之后,都进行了一定的处理,如果出现数据库访问异常,还进行了回滚。而对数据库的插入和更新,则是调用的真实主题类的实现。也就是说,代理类只帮我们完成一些辅助功能,核心功能有我们用户自己定义,并传进去。
下面是测试代码:
package org.lyk.main; import other.*; public class Main
{
public static void main(String[] args) throws Exception
{
DAOImplProxy proxy = new DAOImplProxy(new DAOImpl());
IDAO<Integer,Dept> dao = (IDAO<Integer, Dept>)proxy;
dao.doCreate(new Dept());
}
}
从上面的解释可以看出,我们每个代理类都和固定的真实实现类绑定在了一起,因为该代理类只能完成DAOImpl类的这些功能。如果我们有另外一个对IDAO<K,V>的实现,我们又不得不再写一个代理类,悲剧的事我们的数据库往往有几十甚至几百张表。而且这种紧耦合方式在软件设计/开发中应该是尽量回避的。
上面是我们自己实现的代理模式设计,其实JAVA对代理模式已经有对应的支持。利用Proxy类和InvocationHandler接口可以实现动态代理模式设计。
动态代理模式中的代理类不再继承某一个特定的接口,而是实现InvocationHandler接口。同样,持有一个对真实对象的引用(该引用由我们在运行时动态传入)。在invoke中实现对数据库的访问调用。
package other; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class DAOImplProxy implements InvocationHandler
{
private Object realObject = null; public DAOImplProxy(Object realObject)
{
this.realObject = realObject;
} private void updatePre()
{
System.out.println("===取消自动提交===");
} private void updateAfter()
{
System.out.println("===设置自动提交===");
} private void roolBack()
{
System.out.println("===事务出现异常,回滚===");
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
try
{
this.updatePre();
Object retVal = method.invoke(this.realObject, args);
this.updateAfter();
return retVal;
}
catch(Exception e)
{
this.roolBack();
e.printStackTrace();
throw e; }
}
}
上面使用了JAVA中反射功能实现对DAOImpl中方法的调用。
测试代码:
package org.lyk.main; import java.lang.reflect.Proxy; import other.*; public class Main
{
public static void main(String[] args) throws Exception
{
//真实的对数据库的访问功能
DAOImpl di = new DAOImpl();
//将真实功能实例传入代理类中
DAOImplProxy proxy = new DAOImplProxy(di);
//通过Proxy获取代理主题的实例
Object proxyInstance = Proxy.newProxyInstance(di.getClass().getClassLoader(),di.getClass().getInterfaces(), proxy);
//强转成IDAO接口
IDAO<Integer,Dept> dao = (IDAO<Integer, Dept>)proxyInstance;
//实现对数据库的访问
dao.doCreate(new Dept());
}
}
Java中的代理模式的更多相关文章
- (转)轻松学,Java 中的代理模式及动态代理
背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...
- 说说Java中的代理模式
今天看到传智播客李勇老师的JDBC系列的第36节——通过代理模式来保持用户关闭连接的习惯.讲的我彻底蒙蔽了,由于第一次接触代理模式,感到理解很难,在博客园找到一篇文章,先记录如下: 引用自java设计 ...
- 谈谈Java中的代理模式
首先来看一下代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用, 其特征是代理类与 ...
- 深入理解JAVA中的代理模式
前言 代理是什么 事故现场:我家的宠物今天生病了,而我又没有相关的医学知识,所以我只让我的宠物多喝热水吗? 结果显然是不行的,所以我需要去找宠物医生这些更专业的人来帮我的宠物治病. 这个时候,代理就出 ...
- Java中的代理模式--静态代理和动态代理本质理解
代理模式定义:为其他对象提供了一种代理以控制对这个对象的访问. 代理模式的三种角色: Subject抽象主题角色:抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求. Real ...
- 实例_ Java中的代理模式
静态代理 我们定义一个接口,并且使用代理模式,想要做到的就是在调用这个接口的实现类时在此方法上添加功能. public interface HelloInterface { void sayHello ...
- Java 中的代理模式及动态代理
原文:https://blog.csdn.net/briblue/article/details/73928350
- Objective-C中的委托(代理)模式
我个人更喜欢把委托(Delegate)模式称为代理(Proxy)模式.还是那句话,第一次接触代理模式是在Java中接触的,在Java中实现代理模式和接口是少不了的.当时学习Spring的时候用到了接口 ...
- Java设计模式:代理模式(转)
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...
随机推荐
- 了解Sql Server的执行计划
前一篇总结了Sql Server Profiler,它主要用来监控数据库,并跟踪生成的sql语句.但是只拿到生成的sql语句没有什么用,我们可以利用这些sql语句,然后结合执行计划来分析sql语句的性 ...
- WCF初探-10:WCF客户端调用服务
创建WCF 服务客户端应用程序需要执行下列步骤: 获取服务终结点的服务协定.绑定以及地址信息 使用该信息创建 WCF 客户端 调用操作 关闭该 WCF 客户端对象 WCF客户端调用服务存在以下特点: ...
- Android MediaPlayer和SurfaceView播放视频
昨天介绍了VideoView播放视频,今天再介绍一种播放视频的方法MediaPlayer和SurfaceView,MediaPlayer播放音频,SurfaceView来显示图像,具体步骤如下: 1. ...
- hehe
with wares as ( SELECT distinct a.Wid as wid, a.Wname as wareName, a. ...
- IOS开发支付宝集成思路
一般情况下支付功能的交互流程 比如我们去某个APP去支付一个产品,流程为:1.用户点击支付->2.客户端请求服务器用户支付->3.服务器接收请求生成金额订单等要给第三方支付的一切信息,并生 ...
- Android中的五大布局
Android中的五大布局 1.了解布局 一个丰富的界面总是要由很多个控件组成的,那我们如何才能让各个控件都有条不紊地 摆放在界面上,而不是乱糟糟的呢?这就需要借助布局来实现了.布局是一种可用于放置很 ...
- PyCharm5.0.2最新版破解注册激活码(图文版)
下载PyCharm http://download-cf.jetbrains.com/python/pycharm-professional-5.0.2.exe 安装PyCharm 设置激活服务器 ...
- sqlite3使用(一)
最近工作接触到sqlite3了,于是用博客记录下,当然只是浅用哈! 参考资料:http://www.runoob.com/sqlite/sqlite-tutorial.html 概念: SQLite ...
- iOS开发中检测版本,有新版本则更新
iOS程序自动提示更新的实现方案大致分为两种: 第一种,自己服务器提供一个接口,告知相关app的当前版本,是否需要更新,以及更新的地址等信息 . 第二种,就是利用苹果的appstore 提供的相关ap ...
- Python条件语句
1.简介 多个条件判断,用elif语句. 如果判断需要多个条件需同时判断时,可以使用 or (或),表示两个条件有一个成立时判断条件成功: 使用 and (与)时,表示只有两个条件同时成立的情况下,判 ...