概述

代理模式(Proxy Pattern)是指为其他对象提供一种代理,以控制对这个对象的访问。
代理对象在客户端和目标对象之间起到中介作用,代理模式属于结构型设计模式。使用
代理模式主要有两个目的:一保护目标对象,二增强目标对象。

静态代理

静态代理很简单,就是代理对象持有目标对象的引用,通过调用代理对象的方法简介调用目标对象。简单看下代码:

  1. /**
  2. * 通用Mapper接口
  3. *
  4. * @author xingxingwu.hand-china.com
  5. */
  6. public interface Mapper {
  7. /**
  8. * 保存接口
  9. *
  10. * @return 保存后的数据
  11. */
  12. public void save();
  13. }
  14. /**
  15. * UserMapper
  16. *
  17. * @author xingxingwu.hand-china.com
  18. */
  19. public class UserMapper implements Mapper {
  20. @Override
  21. public void save() {
  22. System.out.println("保存用户成功");
  23. }
  24. }
  25. /**
  26. * 事务代理处理器
  27. *
  28. * @author xingxingwu.hand-china.com
  29. */
  30. public class TransactionHandler implements Mapper {
  31. private Mapper target;
  32. public TransactionHandler(Mapper target) {
  33. this.target = target;
  34. }
  35. @Override
  36. public void save() {
  37. System.out.println("开启事务");
  38. try {
  39. target.save();
  40. System.out.println("关闭事务");
  41. } catch (Exception e) {
  42. System.out.println("事务回滚");
  43. }
  44. }
  45. }
  46. public class Client {
  47. public static void main(String[] args) {
  48. TransactionHandler transactionHandler = new TransactionHandler(new UserMapper());
  49. transactionHandler.save();
  50. }
  51. }
  52. 执行结果:
  53. 开启事务
  54. 保存用户成功
  55. 关闭事务

静态代理有很大的局限性,只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步
新增,违背开闭原则。

动态代理

动态代理和静态对比基本思路是一致的,只不过动态代理功能更加强大,随着业务的扩展适应性更强。使用动态代理相当于是能够适应复杂的业务场景。

JDK动态代理

还是以事务处理为例,我们修改TransactionHandler的实现方式:

  1. **
  2. * 事务代理处理器
  3. *
  4. * @author xingxingwu.hand-china.com
  5. */
  6. public class TransactionHandler implements InvocationHandler {
  7. private Object target;
  8. public TransactionHandler(Object target) {
  9. this.target = target;
  10. }
  11. public static Object getInstance(Object target) {
  12. Class<?> clazz = target.getClass();
  13. return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new TransactionHandler(target));
  14. }
  15. @Override
  16. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  17. System.out.println("开启事务");
  18. Object obj = null;
  19. try {
  20. obj = method.invoke(this.target, args);
  21. System.out.println("关闭事务");
  22. } catch (Exception e) {
  23. System.out.println("事务回滚");
  24. }
  25. return obj;
  26. }
  27. }

客户端逻辑也要修改:

  1. public class Client {
  2. public static void main(String[] args) {
  3. Mapper userMapper = (Mapper) TransactionHandler.getInstance(new UserMapper());
  4. userMapper.save();
  5. }
  6. }
  7. 执行结果:
  8. 开启事务
  9. 保存用户成功
  10. 关闭事务

上述代码我们基于JDK Proxy实现了动态代理。JDK Proxy底层是基于字节码重组实现的。如果想了解实现源码,请参考另外一篇文章