【Java技术点滴】——代理模式及其对事务封装

背景

项目中我们会遇到这样的情况:在几个方法中加入相同的代码,这些代码是与业务无关的,并且以后有可能由于考虑不周或需求变动再或者是其他原因,我们需要对他们进行逐一进行改动。举个具体的例子,比如程序中的日志控制、事务控制等,这些功能是与业务无关的,但却需要将它们与我们的逻辑混在一起,达到一些特殊的需求。

这样的情况往往代码都是相同的,可以抽离出来,为了复用,我们可以将这些相同的代码单独封装成的方法,以供其他需要的地方调用,这样对于以后的修改就做到了只修改一处的效果,达到了程序的复用,但另外一个问题便是,将来某一天我们可能不需要这样的功能了,我们就需要将调用这些功能的代码逐一进行删除,而且当方法的参数或返回值变动也许要进行每一处调用的修改。

基于以上的问题,我们可以采用代理模式进行解决。

基本介绍

代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。

直白些说,我们与需要调用的目标对象之间加上一层(代理类),我们便不直接调用以前的目标对象,而是通过代理类间接调用,这样,我们就可以在代理里做那些抽离出的功能了。

代理模式类图示意

以前的直接调用方式

使用代理模式抽取公共调用部分

分类

静态:

静态代理中的代理类是看得见摸得着的,编译时就已经确定了要执行的方法。静态代理存在着代理类过多的问题。为了更加灵活度的实现,我们可以使用动态代理。

动态:代理类运行时确定

使用:

1.目标类必须实现某接口

2.建立代理对象的控制类

实现InvocationHandler,封装根据目标对象生成代理类的方法,调用方首先调用Proxy的newProxyInstance方法(此部分可以应用工厂模式进行封装,以后可以进行去除或改变代理类),生成并转换为代理类,调用此类的目标方法,则可回调到InvocationHandler实现类的invoke方法

示例-动态代理封装事务

public class TransactionHandler implements InvocationHandler {private Object targetObject;public Object newProxyInstance(Object targetObject){this.targetObject = targetObject;return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),<span style="font-family:KaiTi_GB2312;">      </span>targetObject.getClass().getInterfaces(), this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{Connection conn = null;Object ret = null;try{conn = ConnectionManager.getConnection();//开启事务的配置可采用配置文件,那样可更加灵活if(method.getName().startsWith("save") ||    method.getName().startsWith("remove") ||   method.getName().startsWith("modify")){   //手动控制事务提交       ConnectionManager.beginTransaction(conn);}//调用目标对象的业务逻辑方法ret = method.invoke(targetObject, args);//判断,当AutoCommit设置为false的前提下控制提交if(!conn.getAutoCommit()){//提交事务ConnectionManager.commit(conn);}}catch(Exception e){e.printStackTrace();//动态代理对我们自定义的异常进行了封装if(e instanceof InvocationTargetException){InvocationTargetException ete = (InvocationTargetException)e;throw ete.getTargetException();}//回滚事务ConnectionManager.rollbackTransaction(conn);throw new ApplicationException("操作失败!");}finally{ConnectionManager.closeConnection();}return ret;}}

注:此示例中的类ConnectionManage具体实现参见【Java技术点滴】——ThreadLocal封装JDBC事务操作

经过此类的封装,我们便可以实现在Service层中需要进行事务操作的地方便不用每次都写事务相关的代码了,只要为Service层类生成代理,回调此类的的Invoke方法就可以实现事务的控制,这样就达到了很好的复用和更高的可维护性。

总结

正因为代理模式为我们带来了类似于Filter的拦截机制,使我们可以在调用目标方法前做一些事,在调用目标方法后做一些事,这样就可以达到以前我们一般的编程理论所不能达到的效果,再加上一些灵活配置的附加应用,代理模式的应用可以说是相当广泛,也为今后的程序设计提供了更多了思路与思想。

我躺下来,以一张报纸当枕头。高高在我上方的,

【Java技术点滴】——代理模式及其对事务封装

相关文章:

你感兴趣的文章:

标签云: