• 【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的拦截机制,使我们能够在调用目标方法前做一些事,在调用目标方法后做一些事。这样就能够达到曾经我们一般的编程理论所不能达到的效果,再加上一些灵活配置的附加应用,代理模式的应用能够说是相当广泛。也为未来的计划,旨在提供了很多其他的思路和想法。


    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    数据访问 之 修改数据 (重要)---2017-04-27
    数据访问 之 删除操作 ------ 2017-04-27
    连接数据库的注册、登录----2017-04-26
    数据访问(创建链接、读取数据、例题)--2017-04-25
    C/S 和B/S 详解 --- 2017-04-25
    二阶段测试改错与反思(数据库+面向对象)----2017-04-24
    qq面板(仿版,未完待续中。。。。)---2017-04-24
    网站设计需要注意的20个常犯错误---2017-04-23
    数据库四大特性;
    数据库部分---查询-简单查询;
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4737875.html
Copyright © 2020-2023  润新知