代理模式
来源:互联网 发布:周春芽绿狗 知乎 编辑:程序博客网 时间:2024/06/06 03:48
代理模式
1、代理模式
1.1、应用场景
当程序涉及修改数据库中数据操作时,此时的一般操作流程是:
- 1、开启事务
- 2、修改操作
- 3、提交事务或者回滚事务
随着时间的推移,代码中开启事务、提交事务及回滚事务的代码将变得冗余。记录日志在程序中也是推荐使用,那么记录日志也将变得冗余,同时设计具体业务操作的时候,往往还得考虑事务、日志等方面的操作,不能专注于业务操作。
为了解决代码冗余以及业务对象专注于业务操作,产生了代理模式。
1.2、组成部分
代理模式有以下5部分组成:
- 1、target(目标对象/业务对象)
- 2、proxy(代理对象)
- 2、function(功能对象/事务对象、日志对象)
- 3、interceptor(拦截器对象)
- 4、client(客户端)
2、静态代理模式
通过代理类去完成目标类的目标方面,并且在该目标的类特定的代理类中附加上额外的功能
静态代理模式代码实例:
目标类接口
/*** @ClassName: PersonDao* @Description: PersonDao接口* @author Yue Chang * @date 2017年3月23日 上午10:42:46 * @since 1.0*/public interface PersonDao { public void deletePerson(); public void updatePerson();}
目标类实现类
/*** @ClassName: PersonDaoImpl* @Description: PersonDao接口实现类* @author Yue Chang * @date 2017年3月23日 上午10:42:05 * @since 1.0*/public class PersonDaoImpl implements PersonDao { @Override public void deletePerson() { System.out.println("delete Person !~"); } @Override public void updatePerson() { System.out.println("update Person !~"); }}
事务类
/*** @ClassName: Transaction* @Description: 事务类* @author Yue Chang * @date 2017年3月23日 上午10:45:19 * @since 1.0*/public class Transaction { public void beginTransaction(){ System.out.println("begin transaction !~"); } public void commit(){ System.out.println("transaction commit !~"); } public void rollback(){ System.out.println("transaction rollback !~"); }}
拦截器类
/*** @ClassName: MyHandler* @Description: 拦截器类* @author Yue Chang * @date 2017年3月23日 上午11:54:30 * @since 1.0*/public class MyHandler implements PersonDao { private Transaction transaction; private PersonDao personDaoTarget; /** * @param transaction * @param personDao */ public MyHandler(Transaction transaction, PersonDao personDao) { super(); this.transaction = transaction; this.personDaoTarget = personDao; } @Override public void deletePerson() { try { // 开启事务 transaction.beginTransaction(); // 目标类对象调用目标方法 personDaoTarget.deletePerson(); // 提交事务 transaction.commit(); } catch (Exception e) { // 回滚事务 transaction.rollback(); } } @Override public void updatePerson() { try { // 开启事务 transaction.beginTransaction(); // 目标类对象调用目标方法 personDaoTarget.updatePerson(); // 提交事务 transaction.commit(); } catch (Exception e) { // 回滚事务 transaction.rollback(); } } public Transaction getTransaction() { return transaction; } public void setTransaction(Transaction transaction) { this.transaction = transaction; } public PersonDao getPersonDaoTarget() { return personDaoTarget; } public void setPersonDaoTarget(PersonDao personDaoTarget) { this.personDaoTarget = personDaoTarget; }}
客户端对象
/*** @ClassName: StaticProxyTest* @Description: 静态代理模式测试类* @author Yue Chang * @date 2017年3月23日 下午12:01:49 * @since 1.0*/public class StaticProxyTest { @Test public void testStaticProxy(){ PersonDao personDao = new PersonDaoImpl(); Transaction transaction = new Transaction(); MyHandler myHandler = new MyHandler(transaction, personDao); myHandler.deletePerson(); System.out.println(); myHandler.updatePerson(); }}
程序执行结果:
begin transaction !~delete Person !~transaction commit !~begin transaction !~update Person !~transaction commit !~
优点:。
1、可以在不改变目标类的基础上,增加额外的功能,耦合度低;
2、让目标类专注于业务开发,无需关注业务之外的功能;
缺点:
1、对于每一个目标类都需要编写一个handler,代码冗余,增加代码维护成本;
3、动态代理
为了解决静态代理模式的代码冗余的缺点,以及继续保持低耦合的优点,也就有了动态代理模式。其中包括cglib动态代理模式和jdk动态代理模式。
3.1 jdk动态代理模式
jdk动态代理模式代码实例:
PersonDao接口
/*** @ClassName: PersonDao* @Description: PersonDao接口* @author Yue Chang * @date 2017年3月23日 上午10:42:46 * @since 1.0*/public interface PersonDao { public void deletePerson(); public void updatePerson();}
PersonDao接口实现类
/*** @ClassName: PersonDaoImpl* @Description: PersonDao接口实现类* @author Yue Chang * @date 2017年3月23日 上午10:42:05 * @since 1.0*/public class PersonDaoImpl implements PersonDao { @Override public void deletePerson() { System.out.println("delete Person !~"); } @Override public void updatePerson() { System.out.println("update Person !~"); }}
功能类(事务类)
/*** @ClassName: Transaction* @Description: 事务类* @author Yue Chang * @date 2017年3月23日 上午10:45:19 * @since 1.0*/public class Transaction { public void beginTransaction(){ System.out.println("begin transaction !~"); } public void commit(){ System.out.println("transaction commit !~"); } public void rollback(){ System.out.println("transaction rollback !~"); }}
拦截器
/** * @ClassName: MyHandler * @Description: 拦截器 * @author Yue Chang * @date 2017年3月23日 上午10:49:05 * @since 1.0 */public class MyHandler implements InvocationHandler { private Object target; private Transaction transaction; /** * @param target 目标对象 * @param tansaction 事务对象 */ public MyHandler(Object target, Transaction transaction) { super(); this.target = target; this.transaction = transaction; } // invoke方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // 开启事务 transaction.beginTransaction(); // 调用目标类的目标方法, method.invoke(target, args); // 提交事务 transaction.commit(); } catch (Exception e) { // 回滚事务 transaction.rollback(); } return null; } // getter/setter方法}
客户端测试类
/*** @ClassName: JdkProxyTest* @Description: jdk动态代理客户端* @author Yue Chang * @date 2017年3月23日 上午10:56:36 * @since 1.0*/public class JdkProxyTest { @Test public void testJdkProxy(){ // 目标对象 PersonDao target = new PersonDaoImpl(); // 事务对象 Transaction transaction = new Transaction(); // 拦截器对象 MyHandler myIntercepter = new MyHandler(target, transaction); // PersonDao代理对象 PersonDao proxy = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myIntercepter); proxy.deletePerson(); System.out.println(); proxy.updatePerson(); }}
代码执行结果:
begin transaction !~delete Person !~transaction commit !~begin transaction !~update Person !~transaction commit !~
如果想再加入其他功能,比如日志,则需要在MyHandler类中,新增成员变量Logger,修改对应的构造方法,在invoke方法中增加对应操作。同时,如果觉得不需要事务,也同样可以操作MyHandler类来去除事务,这样的操作与目标类没有任何影响,完全松耦合。
3.2 cglib动态代理模式
cglib动态代理模式与jdk动态代理模式类似,cglib动态代理模式代码如下:
PersonDao接口
/*** @ClassName: PersonDao* @Description: PersonDao接口* @author Yue Chang * @date 2017年3月23日 上午10:42:46 * @since 1.0*/public interface PersonDao { public void deletePerson(); public void updatePerson();}
PersonDao接口实现类
/*** @ClassName: PersonDaoImpl* @Description: PersonDao接口实现类* @author Yue Chang * @date 2017年3月23日 上午10:42:05 * @since 1.0*/public class PersonDaoImpl implements PersonDao { @Override public void deletePerson() { System.out.println("delete Person !~"); } @Override public void updatePerson() { System.out.println("update Person !~"); }}
事务类
/*** @ClassName: Transaction* @Description: 事务类* @author Yue Chang * @date 2017年3月23日 上午10:45:19 * @since 1.0*/public class Transaction { public void beginTransaction(){ System.out.println("begin transaction !~"); } public void commit(){ System.out.println("transaction commit !~"); } public void rollback(){ System.out.println("transaction rollback !~"); }}
cglib代理类拦截器
/** * @ClassName: MyInterceptor * @Description: cglib代理类拦截器 * @author Yue Chang * @date 2017年3月23日 下午12:19:35 * @since 1.0 */public class MyInterceptor implements MethodInterceptor { private Object target; private Transaction transaction; /** * @param target * @param transaction */ public MyInterceptor(Object target, Transaction transaction) { super(); this.target = target; this.transaction = transaction; } /** * @category 创建代理对象,可以在客户端完成 * @since cglib proxy * @author Yue Chang * @date 2017年3月31日 上午11:41:50 * @return */ public Object createProxy(){ Enhancer enhancer = new Enhancer(); enhancer.setCallback(this); enhancer.setSuperclass(target.getClass()); return enhancer.create(); } @Override public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable { try { transaction.beginTransaction(); method.invoke(target, args); transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } return null; } // getter/setter方法}
客户端
/*** @ClassName: CglibProxyTest* @Description: cglib代理模式测试类* @author Yue Chang * @date 2017年3月25日 下午3:48:01 * @since 1.0*/public class CglibProxyTest { @Test public void testCglibProxy(){ PersonDao target = new PersonDaoImpl(); Transaction transaction = new Transaction(); MyInterceptor myInterceptor = new MyInterceptor(target, transaction); PersonDao proxy = (PersonDao) myInterceptor.createProxy(); proxy.deletePerson(); System.out.println(); proxy.updatePerson(); }}
程序运行结果:
begin transaction !~delete Person !~transaction commit !~begin transaction !~update Person !~transaction commit !~
3.3 jdk动态代理模式和cglib动态代理模式的区别
均在invoke方法中,对于复杂的逻辑处理比较困难。其中,具体方法由对应method参数决定。
jdk动态代理模式中,是通过Proxy.newProxyInstance来创建代理对象;
cglib动态代理模式中,是通过Enhancer对象来创建代理对象;
jdk动态代理模式中,代理类与目标类实现了相同的接口;
cglib动态代理模式中,代理类是目标类的子类;
这一点区别其实也可以从创建代理对象中发现,jdk的获得目标类以及目标类的所有接口
Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myIntercepter);
cglib 将目标类设置为代理对象的超类
Enhancer enhancer = new Enhancer(); enhancer.setCallback(this); enhancer.setSuperclass(target.getClass()); return enhancer.create();
4、拓展
可以申明一个Interceptor类,里面定义interceptor方法,将所有需要附加的功能类都实现Interceptor接口,将需要的操作在interceptor方法中实现,然后在动态代理模式中定义List interceptorList成员变量,初始化时传入interceptorList,在invoke方法中迭代此List,并执行Interceptor对象的interceptor方法,这样可以执行附加多个功能,并且不频繁改动拦截器类。
- 代理模式--动态代理
- 代理模式-静态代理
- 代理模式-静态代理
- 代理模式 & 动态代理
- 代理模式--静态代理
- 代理模式--动态代理
- 代理模式(动态代理)
- 代理模式-动态代理
- 代理模式-动态代理
- 代理模式动态代理
- 代理模式-静态代理
- 代理模式-动态代理
- 代理模式 -动态代理
- 代理模式---动态代理
- 代理模式-动态代理
- 代理模式--静态代理
- 代理模式!
- 代理模式
- SetWindowPos函数详解及CenterWindow()的用法
- ESB v6.5.1,ESB6.5.1studio导出的ecd部署包,通过Governor部署到Linux系统的服务器上,提示“目标文件类型不合法”。
- 批量梯度下降算法BGD,小批量梯度下降法MBGD,随机梯度下降算法SGD的比较
- 小波的秘密8_图像处理应用:图像降噪
- Android 发送验证码倒计时常用的两种办法
- 代理模式
- Error:Execution failed for task ':app:resolveDebugDependencies'. > Could not initialize class com.an
- 一个demo让你彻底搞懂观察者模式
- 如何删除C++容器中的值
- 小波的秘密9_图像处理应用:图像增强
- PHP获取今日、本周、本月、本年初始(凌晨)时间戳的方法
- C++ 运算符重载
- Linux 改写rm命令,让删除编程备份
- ESB v6.5.1,ESB Server MQ服务启动失败--启动报java.net.UnknownHostException: bogon: bogon