概述
代理模式(Proxy Pattern)是指为其他对象提供一种代理,以控制对这个对象的访问。
代理对象在客户端和目标对象之间起到中介作用,代理模式属于结构型设计模式。使用
代理模式主要有两个目的:一保护目标对象,二增强目标对象。
静态代理
静态代理很简单,就是代理对象持有目标对象的引用,通过调用代理对象的方法简介调用目标对象。简单看下代码:
/*** 通用Mapper接口** @author xingxingwu.hand-china.com*/public interface Mapper {/*** 保存接口** @return 保存后的数据*/public void save();}/*** UserMapper** @author xingxingwu.hand-china.com*/public class UserMapper implements Mapper {@Overridepublic void save() {System.out.println("保存用户成功");}}/*** 事务代理处理器** @author xingxingwu.hand-china.com*/public class TransactionHandler implements Mapper {private Mapper target;public TransactionHandler(Mapper target) {this.target = target;}@Overridepublic void save() {System.out.println("开启事务");try {target.save();System.out.println("关闭事务");} catch (Exception e) {System.out.println("事务回滚");}}}public class Client {public static void main(String[] args) {TransactionHandler transactionHandler = new TransactionHandler(new UserMapper());transactionHandler.save();}}执行结果:开启事务保存用户成功关闭事务
静态代理有很大的局限性,只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步
新增,违背开闭原则。
动态代理
动态代理和静态对比基本思路是一致的,只不过动态代理功能更加强大,随着业务的扩展适应性更强。使用动态代理相当于是能够适应复杂的业务场景。
JDK动态代理
还是以事务处理为例,我们修改TransactionHandler的实现方式:
*** 事务代理处理器** @author xingxingwu.hand-china.com*/public class TransactionHandler implements InvocationHandler {private Object target;public TransactionHandler(Object target) {this.target = target;}public static Object getInstance(Object target) {Class<?> clazz = target.getClass();return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new TransactionHandler(target));}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("开启事务");Object obj = null;try {obj = method.invoke(this.target, args);System.out.println("关闭事务");} catch (Exception e) {System.out.println("事务回滚");}return obj;}}
客户端逻辑也要修改:
public class Client {public static void main(String[] args) {Mapper userMapper = (Mapper) TransactionHandler.getInstance(new UserMapper());userMapper.save();}}执行结果:开启事务保存用户成功关闭事务
上述代码我们基于JDK Proxy实现了动态代理。JDK Proxy底层是基于字节码重组实现的。如果想了解实现源码,请参考另外一篇文章
