Spring 学习(六)代理模式

10. 代理模式

  • 案例

Spring 学习(六)代理模式_第1张图片

10.1 静态代理

  • 角色分析

    • 抽象角色:一般使用接口或者抽象类实现。
    • 真实角色:被代理的角色。
    • 代理角色:代理真实角色,含附属操作。
    • 客户:访问代理对象的角色。
  • 租房案例

    • 定义租赁接口

      /**
       * TODO
       * 租房
       * @author why
       * @since 2021/7/6 9:06
       */
      public interface Rent {
          public void rent();
      }
      
    • 定义真实角色

      /**
       * TODO
       * 房东
       * @author why
       * @since 2021/7/6 9:10
       */
      public class Landlord implements Rent {
      
          public void rent() {
              System.out.println("房东要出租房子");
          }
      }
      
    • 定义代理角色

      /**
       * TODO
       * 中介
       * @author why
       * @since 2021/7/6 9:14
       */
      public class Proxy implements Rent {
          private Landlord landlord;
          public Proxy() {
          }
          public Proxy(Landlord landlord) {
              this.landlord = landlord;
          }
      
          /**
           * 出租房子
           */
          public void rent() {
              seeHouse();
              landlord.rent();
              signContract();
              fee();
          }
      
          /**
           * 看房
           */
          public void seeHouse(){
              System.out.println("中介带租客看房");
          }
      
          /**
           * 收中介费
           */
          public void fee(){
              System.out.println("收中介费");
          }
      
          /**
           * 签合同
           */
          public void signContract(){
              System.out.println("签租赁合同");
          }
          
      }
      
    • 客户端访问代理角色

      /**
       * TODO
       * 租客
       * @author why
       * @since 2021/7/6 9:12
       */
      public class Client {
          public static void main(String[] args) {
              // 房东想要出租房子
              Landlord landlord = new Landlord();
              // 中介帮助房东出租房子,包含了附加操作
              Proxy proxy = new Proxy(landlord);
              // 租客找中介租房子
              proxy.rent();
          }
      }
      
  • 模式优点

    • 可以使真实角色的操作更加纯粹,不必关注一些公共业务。
    • 公共业务交给代理角色,实现了业务的分工。
    • 公共业务发生扩展时,方便集中管理。
  • 模式缺点

    • 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低。
  • 业务模拟

    • 抽象 AOP 机制

    • 定义用户操作接口

      /**
       * TODO
       * 用户服务接口
       * @author why
       * @since 2021/7/6 9:38
       */
      public interface UserService {
          public void add();
          public void delete();
          public void update();
          public void query();
      }
      
    • 定义业务操作实现类

      /**
       * TODO
       * 用户接口实现类(真实对象)
       * @author why
       * @since 2021/7/6 9:40
       */
      public class UserServiceImpl implements UserService {
      
          public void add() {
              System.out.println("增加一个用户");
          }
      
          public void delete() {
              System.out.println("删除一个用户");
          }
      
          public void update() {
              System.out.println("修改一个用户");
          }
      
          public void query() {
              System.out.println("查询一个用户");
          }
      }
      
    • 定义代理

      /**
       * TODO
       * 代理
       * @author why
       * @since 2021/7/6 9:57
       */
      public class UserServiceProxy implements UserService {
      
          private UserService userService;
      
          public void setUserService(UserService userService) {
              this.userService = userService;
          }
      
          public void add() {
              log("add");
              userService.add();
          }
      
          public void delete() {
              log("delete");
              userService.delete();
          }
      
          public void update() {
              log("update");
              userService.update();
          }
      
          public void query() {
              log("query");
              userService.query();
          }
      
          // 日志方法
          public void log(String msg) {
              System.out.println("[Debug] 使用了"+ msg +"方法");
          }
      }
      
    • 定义客户端

      /**
       * TODO
       * 客户端
       * @author why
       * @since 2021/7/6 9:44
       */
      public class Client {
          public static void main(String[] args) {
              UserServiceImpl userService = new UserServiceImpl();
      
              UserServiceProxy userServiceProxy = new UserServiceProxy();
              userServiceProxy.setUserService(userService);
      
              userServiceProxy.add();
          }
      }
      

10.2 动态代理

  • 动态代理和静态代理的角色一样

  • 动态代理的代理类是动态生成的,不需要编写。

  • 动态代理分为基于接口的动态代理和基于类的动态代理。

    • 基于接口 — JDK 动态代理
    • 基于类 — CGLIB
    • Java 字节码实现 — Javasist
  • 租房案例

    • 定义租赁接口

      /**
       * TODO
       * 租房
       * @author why
       * @since 2021/7/6 9:06
       */
      public interface Rent {
          public void rent();
      }
      
    • 定义真实角色(房东)

      /**
       * TODO
       * 房东
       * @author why
       * @since 2021/7/6 9:10
       */
      public class Landlord implements Rent {
      
          public void rent() {
              System.out.println("房东要出租房子");
          }
      }
      
    • 构造代理类生成器

      /**
       * TODO
       * 自动生成代理类
       * @author why
       * @since 2021/7/6 13:43
       */
      public class ProxyInvocationHandler implements InvocationHandler {
      
          // 被代理的接口
          private Rent rent;
      
          public void setRent(Rent rent) {
              this.rent = rent;
          }
      
          // 获得代理类
          public Object getProxy(){
              return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
          }
      
          // 处理代理实例并返回结果
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      
              // 动态代理由反射机制实现
              Object result = method.invoke(rent, args);
              return result;
          }
      }
      
    • 定义客户端

      /**
       * TODO
       * 客户端
       * @author why
       * @since 2021/7/6 13:54
       */
      public class Client {
          public static void main(String[] args) {
      
              // 真实角色
              Landlord landlord = new Landlord();
      
              // 代理角色(由 InvocationHandler 获取)
              ProxyInvocationHandler pih = new ProxyInvocationHandler();
      
              // 通过调用处理程序处理要调用的接口对象
              pih.setRent(landlord);
              Rent proxy = (Rent) pih.getProxy();
              proxy.rent();
          }
      }
      
  • 模式优点

    • 可以使真实角色的操作更加纯粹,不必关注一些公共业务。
    • 公共业务交给代理角色,实现了业务的分工。
    • 公共业务发生扩展时,方便集中管理。
    • 一个动态代理类代理的是一个接口,一般就是一类业务。
    • 一个动态代理可以代理多个类,前提是这些类实现了同一个接口。
  • 业务模拟

    • 定义用户操作接口

      /**
       * TODO
       * 用户服务接口
       * @author why
       * @since 2021/7/6 9:38
       */
      public interface UserService {
          public void add();
          public void delete();
          public void update();
          public void query();
      }
      
    • 定义业务操作实现类

      /**
       * TODO
       * 用户接口实现类(真实对象)
       * @author why
       * @since 2021/7/6 9:40
       */
      public class UserServiceImpl implements UserService {
      
          public void add() {
              System.out.println("增加一个用户");
          }
      
          public void delete() {
              System.out.println("删除一个用户");
          }
      
          public void update() {
              System.out.println("修改一个用户");
          }
      
          public void query() {
              System.out.println("查询一个用户");
          }
      }
      
    • 定义代理生成器

      /**
       * TODO
       * 自动生成代理类
       * @author why
       * @since 2021/7/6 13:43
       */
      public class ProxyInvocationHandler implements InvocationHandler {
      
          // 被代理的接口
          private Object target;
      
          public void setTarget(Object target) {
              this.target = target;
          }
      
          // 获得代理类
          public Object getProxy(){
              return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
          }
      
          // 处理代理实例并返回结果
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      
              log(method.getName());
              // 动态代理由反射机制实现
              return method.invoke(target, args);
          }
      
          public void log(String msg){
              System.out.println("执行了" + msg + "方法");
          }
      }
      
    • 定义客户端

      /**
       * TODO
       * 客户端
       * @author why
       * @since 2021/7/6 15:00
       */
      public class Client {
          public static void main(String[] args) {
              UserServiceImpl userService = new UserServiceImpl();
              ProxyInvocationHandler pih = new ProxyInvocationHandler();
              pih.setTarget(userService);
              UserService proxy = (UserService) pih.getProxy();
              proxy.add();
          }
      }
      

你可能感兴趣的:(Spring,spring,学习,代理模式)