zoukankan      html  css  js  c++  java
  • 18 java 代理模式 (转)

    静态代理

    1、新建一个接口,这个接口所提供的方法是关于数据库操作的

    
    public interface EmployeeDao {
        public void updateSalary();
    }

    2、建一个目标类实现这个接口,这个目标类是我们要进行的业务

    
    public class EmployeeDaoImpl implements EmployeeDao {
        @Override
        public void updateSalary() {
            System.out.println("您的薪水又有更新");
        }
    }

    3、再建一个代理类,为目标对象提供一种代理,并以控制对这个对象的访问。

    
    public class EmployeeDaoProxy implements EmployeeDao{
        private EmployeeDao employeeDao;
        private Transaction transaction;
        public EmployeeDaoProxy(EmployeeDao employeeDao,Transaction transaction) {
            this.employeeDao=employeeDao;
            this.transaction=transaction;
        }
    
        @Override
        public void updateSalary() {
            this.transaction.startTransaction();
            this.employeeDao.updateSalary();
            this.transaction.commit();
        }
        

    由以上可知,代理模式的组成包括:目标接口(抽象角色),目标类(真实角色)和代理类(代理角色)。

    4、代理类代理事务的处理,所以需要增加一个事务类

    
    public class Transaction {
        public void startTransaction(){
            System.out.println("开启事务");
        }
        public void commit(){
            System.out.print("事物提交");
        }
    }

    5、最后我们用一个test case来测试一下

    
    import static org.junit.Assert.*;
    import org.junit.Test;
    public class ProxyTest {
        @Test
        public void test() {
            EmployeeDao target = new EmployeeDaoImpl();
            Transaction transaction = new Transaction();
            EmployeeDao proxy = new EmployeeDaoProxy(target,transaction);
            proxy.updateSalary();
        }
    }
    

    执行情况

    开启事务
    您的薪水又有更新
    事物提交
    

    假设上面的例子中的接口不只一个方法,或是不只一个接口要用到代理,上面的静态代理的代码就太过繁琐和冗余,所以就出现了jdk的动态代理。

    动态代理

    同样以上面的例子做示例

    1和2中的接口和目标类的编写以及4中的事务处理是相同的,在3中,我们引入拦截器的概念,拦截器是实现动态性的核心

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /*
     * 拦截器
     * 引入目标类和事务
     * 通过构造器给目标函数和事务赋值
     * 填充invoke方法
     * 
     */
    public class EmployeeInterceptor implements InvocationHandler{
        private Object target;
        private Transaction transaction;
        public EmployeeInterceptor(Object target, Transaction transaction) {
            
            this.target = target;
            this.transaction = transaction;
        }
        
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            this.transaction.startTransaction();
            method.invoke(this.target, args);
            this.transaction.commit();
            return null;
        }
    }

    同样在test case中作出修改

    
    import static org.junit.Assert.*;
    import java.lang.reflect.Proxy;
    import org.junit.Test;
    public class ProxyTest1 {
        @Test
        public void test() {
            EmployeeDao target = new EmployeeDaoImpl();
            Transaction transaction = new Transaction();
            EmployeeInterceptor interceptor = new  EmployeeInterceptor(target,transaction);
            EmployeeDao  employeeDao = (EmployeeDao)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor);
            employeeDao.updateSalary();
        }
    }

    最后看一下两次执行的情况

    开启事务
    您的薪水又有更新
    事物提交
  • 相关阅读:
    【学习笔记】Hive
    《深入浅出数据分析》笔记
    SQL vs. HQL 语法对比
    log4net日志使用方法
    NLog日志使用方法
    VS2010,C#项目改动后无法编译
    Jquery easyui的datagrid在初始化的时候会请求两次URL?
    【硬件】Realtek RTL9210固件部分参数翻译及移动硬盘WinToGo推荐调优方案
    【小记】RedHat8(CentOS) 下连接数据库ODBC报 SSL Error:141A318A 问题
    【小记】[新手常见错误] C++ 指针的引用
  • 原文地址:https://www.cnblogs.com/yangh2016/p/5938758.html
Copyright © 2011-2022 走看看