Java之代理模式解析

前言

代理模式为目标对象提供代理服务,客户端不直接操作目标对象,而是通过代理类管理对象,是不是有点类似Spring的IoC容器,没错!Spring等框架就是很多技术的融合,设计时融入了许多设计模式的思想。

1. 概念

代理模式是一种结构型设计模式,其主要目的是控制和管理访问对象。代理模式分为三种主要类型:静态代理、动态代理(JDK 动态代理和CGLIB 动态代理),以及虚拟代理。

2. 代理模式种类

  • 静态代理:

    静态代理是在编译阶段就已经确定代理关系,代理类和真实类的关系在代码中是固定的。通过手动编写代理类,在代理类中调用真实类的方法,并可以在方法调用前后进行一些额外的操作。

  • 动态代理:

    动态代理分为JDK动态代理和CGLIB动态代理。在运行时通过反射等机制动态创建代理类,无需在编译期确定代理关系,更加灵活。

  • 虚拟代理:

    虚拟代理是在访问对象时才创建真实对象,适用于资源开销较大的情况。虚拟代理可以延迟真实对象的创建,提高系统性能。
    代理模式的优点包括:

代理模式的优缺点

代理模式的优点包括:

  • 控制对真实对象的访问,可以在访问前后执行一些额外的操作。
  • 隐藏目标对象的实现细节。
  • 降低系统的耦合度。

代理模式的缺点包括:

  • 由于每个代理都要实现一遍目标接口,会导致代码冗余。
  • 增加了系统的复杂度。
    根据实际需求和场景,选择不同类型的代理模式。

3.示例代码

  • 静态代理:
    在静态代理中,代理类是在编译期间就已经确定的,代理类和目标类的关系在代码中是固定的。

          // 接口
       interface Subject {
           void request();
       }
       
       // 真实对象
       class RealSubject implements Subject {
           @Override
           public void request() {
               System.out.println("RealSubject handles request.");
           }
       }
       
       // 代理对象
       class Proxy implements Subject {
           private RealSubject realSubject;
       
           public Proxy(RealSubject realSubject) {
               this.realSubject = realSubject;
           }
       
           @Override
           public void request() {
               // 额外的操作
               System.out.println("Proxy handles request.");
               realSubject.request();
               // 额外的操作
           }
       }
    
    
  • 动态代理(JDK动态代理):
    动态代理是在运行时创建的代理对象,它不需要提前编写代理类,而是通过 Java 反射机制在运行时动态生成。

       import java.lang.reflect.InvocationHandler;
       import java.lang.reflect.Method;
       import java.lang.reflect.Proxy;
       
       // 接口
       interface Subject {
           void request();
       }
       
       // 真实对象
       class RealSubject implements Subject {
           @Override
           public void request() {
               System.out.println("RealSubject handles request.");
           }
       }
       
       // 动态代理处理器
       class DynamicProxyHandler implements InvocationHandler {
           private Object realSubject;
       
           public DynamicProxyHandler(Object realSubject) {
               this.realSubject = realSubject;
           }
       
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               // 额外的操作
               System.out.println("DynamicProxy handles request.");
               Object result = method.invoke(realSubject, args);
               // 额外的操作
               return result;
           }
       }
       
       // 客户端使用动态代理
       public class DynamicProxyExample {
           public static void main(String[] args) {
               RealSubject realSubject = new RealSubject();
               InvocationHandler handler = new DynamicProxyHandler(realSubject);
               Subject proxySubject = (Subject) Proxy.newProxyInstance(
                   realSubject.getClass().getClassLoader(),
                   realSubject.getClass().getInterfaces(),
                   handler
               );
       
               // 调用代理对象
               proxySubject.request();
           }
       }
    
    
  • 动态代理(CGLIB动态代理):

       import net.sf.cglib.proxy.Enhancer;
       import net.sf.cglib.proxy.MethodInterceptor;
       import net.sf.cglib.proxy.MethodProxy;
       
       // 真实对象
       class RealSubject {
           public void request() {
               System.out.println("RealSubject handles request.");
           }
       }
       
       // CGLIB 动态代理处理器
       class CglibProxyHandler implements MethodInterceptor {
           private Object realSubject;
       
           public CglibProxyHandler(Object realSubject) {
               this.realSubject = realSubject;
           }
       
           @Override
           public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
               // 额外的操作
               System.out.println("CglibProxy handles request.");
               Object result = method.invoke(realSubject, objects);
               // 额外的操作
               return result;
           }
       }
       
       // 客户端使用 CGLIB 动态代理
       public class CglibProxyExample {
           public static void main(String[] args) {
               RealSubject realSubject = new RealSubject();
               Enhancer enhancer = new Enhancer();
               enhancer.setSuperclass(RealSubject.class);
               enhancer.setCallback(new CglibProxyHandler(realSubject));
               RealSubject cglibProxy = (RealSubject) enhancer.create();
       
               // 调用代理对象
               cglibProxy.request();
           }
       }
    
    
  • 虚拟代理:
    虚拟代理是在需要的时候才创建和加载目标对象,延迟目标对象的实例化。

       // 接口
       interface Image {
           void display();
       }
       
       // 真实对象
       class RealImage implements Image {
           private String filename;
       
           public RealImage(String filename) {
               this.filename = filename;
               loadImageFromDisk();
           }
       
           private void loadImageFromDisk() {
               System.out.println("Loading image: " + filename);
           }
       
           @Override
           public void display() {
               System.out.println("Displaying image: " + filename);
           }
       }
       
       // 代理对象
       class ProxyImage implements Image {
           private RealImage realImage;
           private String filename;
       
           public ProxyImage(String filename) {
               this.filename = filename;
           }
       
           @Override
           public void display() {
               if (realImage == null) {
                   realImage = new RealImage(filename);
               }
               realImage.display();
           }
       }
       
       // 客户端使用虚拟代理
       public class VirtualProxyExample {
           public static void main(String[] args) {
               // 使用代理对象,实际的图片加载会在调用 display 方法时进行
               Image proxyImage = new ProxyImage("example.jpg");
               proxyImage.display();
           }
       }
    
    

4. 实际开发场景

  • 静态代理常用于简单场景,如权限控制、日志记录等。
  • 动态代理在框架和库中广泛应用,如Spring AOP中的代理。
  • 虚拟代理常用于需要延迟加载的场景,如大图加载。

5.总结

代理模式类型定义示例
静态代理在编译阶段确定代理关系,关系在代码中是固定的。假设有 RealSubject(真实对象)和 Proxy(代理对象)两个类。Proxy 包含对 RealSubject 的引用,并在调用时添加额外的逻辑。
动态代理在运行时通过反射等机制动态创建代理类,更加灵活。1.JDK 动态代理示例:使用 InvocationHandlerProxy 创建动态代理对象,不需要为每个被代理类编写专门的代理类。2.CGLIB 动态代理示例:通过 CGLIB 库创建代理对象,可以代理那些没有实现接口的类。
虚拟代理在访问对象时才创建真实对象,适用于资源开销较大的情况。假设有 Image 接口和具体类 RealImage(真实对象)和 ProxyImage(代理对象)。ProxyImage 在调用 display 方法时才创建并使用 RealImage 对象。
  • 38
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值