目录
  • 定义
  • 分类
  • 案例
    • 需求
    • 方案一:jdk动态代理
    • 方案二:cglib动态代理
  • 分析
    • 总结

      定义

      动态代理指的是,代理类和目标类的关系在程序运行的时候确定的,客户通过代理类来调用目标对象的方法,是在程序运行时根据需要动态的创建目标类的代理对象。

      分类

      jdk动态代理

      cglib动态代理

      案例

      需求

      苹果公司通过苹果代理商来卖手机

      方案一:jdk动态代理

      定义抽象接口

      /**
       * 售卖手机的接口(代理模式——抽象角色)
       * @author:liyajie
       * @createTime:2025/2/22 14:42
       * @version:1.0
       */
      public interface IPhone {
      
          /**
           * 出售手机
           * @author: liyajie
           * @date: 2025/2/22 14:44
           * @param
           * @return void
           * @exception:
           * @update:
           * @updatePerson:
           **/
          void sellPhone();
      }

      定义目标类实现接口,重写接口方法

      /**
       * 苹果公司(代理模式——目标角色)
       * @author:liyajie
       * @createTime:2025/2/22 14:46
       * @version:1.0
       */
      public class TargetPhone implements IPhone {
          @Override
          public void sellPhone() {
              System.out.println("苹果公司正在出售手机");
          }
      }

      定义代理类

      /**
       * 代理商(代理模式——代理角色)
       * @author:liyajie
       * @createTime:2025/2/22 14:50
       * @version:1.0
       */
      public class ProxyPhone {
      
          private Object target;
      
          public ProxyPhone(Object target){
              this.target = target;
          }
      
          public Object getProxyInstance() {
              return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                      target.getClass().getInterfaces(),
                      new InvocationHandler() {
                          @Override
                          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                              System.out.println("JDK动态代理开始之前,添加业务逻辑XXX");
                              //使用反射机制来调用目标对象的方法:解决了问题二
                              Object invoke = method.invoke(target, args);
                              System.out.println("JDK动态代理结束之后,添加业务逻辑XXX");
                              return invoke;
                          }
                      });
          }
      }

      定义测试类

      /**
       * 测试类
       * @author:liyajie
       * @createTime:2025/2/23 15:15
       * @version:1.0
       */
      public class Test {
          public static void main(String[] args) {
              // 创建目标类
              TargetPhone targetPhone = new TargetPhone();
              // 创建代理类
              IPhone iPhone = (IPhone) new ProxyPhone(targetPhone).getProxyInstance();
              System.out.println(iPhone.getClass());
              // 通过代理类调用目标方法
              iPhone.sellPhone();
          }
      }

      查看测试结果

      方案二:cglib动态代理

      定义目标类

      /**
       * 苹果公司(代理模式——目标角色)
       * @author:liyajie
       * @createTime:2025/2/22 14:46
       * @version:1.0
       */
      public class TargetPhone {
      
          public void sellPhone() {
              System.out.println("苹果公司正在出售手机");
          }
      }

      定义代理工厂,用来获取代理类

      /**
       * 代理工厂
       * @author:liyajie
       * @createTime:2025/2/23 15:32
       * @version:1.0
       */
      public class ProxyFactory implements MethodInterceptor {
      
          private Object target;
      
          public ProxyFactory(Object target){
              this.target = target;
          }
      
          public Object getProxyInstance(){
              // 创建一个工具类
              Enhancer enhancer = new Enhancer();
              // 设置父类
              enhancer.setSuperclass(target.getClass());
              // 设置回调函数
              enhancer.setCallback(this);
              // 创建子类对象,即代理对象
              return enhancer.create();
          }
      
          @Override
          public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
              System.out.println("cglib动态代理开始之前,添加业务逻辑xxxx");
              Object invoke = method.invoke(target, objects);
              System.out.println("cglib动态代理之后,添加业务逻辑");
              return invoke;
          }
      }

      定义测试类

      /**
       * 测试类
       * @author:liyajie
       * @createTime:2025/2/23 15:44
       * @version:1.0
       */
      public class Test {
          public static void main(String[] args) {
              // 创建目标对象
              TargetPhone targetPhone = new TargetPhone();
              // 获取代理对象
              TargetPhone proxyInstance = (TargetPhone)new ProxyFactory(targetPhone).getProxyInstance();
              // 通过代理对象调用具体的方法
              proxyInstance.sellPhone();
          }
      }

      查看测试结果

      分析

      首先可以看到不管是jdk动态代理,还是cglib动态代理,实现的效果和静态代理是一模一样的,都实现了功能的扩展。但是两种动态代理还是有些不同的,其中jdk动态代理需要目标对象实现接口,但是cglib动态代理不需要,因为他是在内存中构建一个子类对象,从而实现对目标对象的功能扩展。

      总结

      通过案例,我们了解了代理模式的几种实现方式,下面我们总结下该模式:

      优势:

      • 代理模式在客户端和目标对象之间起到了一个中介和保护的作用
      • 代理对象可以对目标对象进行功能的扩展和业务的扩展,增强目标对象
      • 代理模式可以将客户端和目标对象分离,在一定程度上降低了系统的耦合度

      劣势:

      • 请求需要经过代理对象,会导致处理速度变慢
      • 因为会有大量的代理对象产生,会增加系统的复杂度