代理模式(详解)

目录

一、什么是代理模式?

二、代理模式的类型

1. 静态代理

2. 动态代理

3. CGLIB代理

三、代理模式的应用场景

四、总结


讲一讲代理模式

代理模式(Proxy Pattern)是结构型设计模式之一,它为其他对象提供一种代理以控制对这个对象的访问。代理模式可以在不改变原始对象的情况下,为其增加额外的功能。本文将详细介绍代理模式,包括其定义、类型、优缺点及其实现方式。

一、什么是代理模式?

代理模式是一种结构型设计模式,它为对象提供了一个代理,并由代理对象控制对原对象的访问。这可以是出于安全、性能、事务等多种原因。

简单来说,代理模式就是通过代理对象来控制对实际对象的访问。代理对象在客户端和目标对象之间起到了中介的作用。

二、代理模式的类型

代理模式主要分为以下几种类型:

  1. 静态代理(Static Proxy)
  2. 动态代理(Dynamic Proxy)
  3. CGLIB代理(Code Generation Library Proxy)

1. 静态代理

静态代理是在代码编译阶段就已经生成了代理类,代理类需要实现与目标对象相同的接口。

优点:

  • 可以在不修改目标对象的前提下对目标对象的方法进行增强。

缺点:

  • 需要为每个目标对象创建一个代理类,导致系统中类的数量增加,维护成本较高。

静态代理模式图:

 

示例代码:

// 抽象接口
public interface Service {
    void performOperation();
}

// 目标对象
public class RealService implements Service {
    public void performOperation() {
        System.out.println("Performing operation in RealService");
    }
}

// 代理对象
public class ServiceProxy implements Service {
    private RealService realService;

    public ServiceProxy(RealService realService) {
        this.realService = realService;
    }

    public void performOperation() {
        System.out.println("Proxy: Before operation");
        realService.performOperation();
        System.out.println("Proxy: After operation");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        RealService realService = new RealService();
        Service proxy = new ServiceProxy(realService);
        proxy.performOperation();
    }
}

2. 动态代理

动态代理是在程序运行时,通过反射机制动态生成的代理类。Java提供了java.lang.reflect.Proxy类来实现动态代理。

优点:

  • 可以为多个目标对象创建一个代理类,减少了类的数量。
  • 代理类的生成是在运行时完成的,可以更加灵活地处理不同的情况。

缺点:

  • 由于使用了反射机制,性能相对静态代理略低。

 动态代理模式类图:

示例代码:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 抽象接口
public interface Service {
    void performOperation();
}

// 目标对象
public class RealService implements Service {
    public void performOperation() {
        System.out.println("Performing operation in RealService");
    }
}

// 动态代理处理器
public class ServiceInvocationHandler implements InvocationHandler {
    private Object target;

    public ServiceInvocationHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Proxy: Before operation");
        Object result = method.invoke(target, args);
        System.out.println("Proxy: After operation");
        return result;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        RealService realService = new RealService();
        ServiceInvocationHandler handler = new ServiceInvocationHandler(realService);
        Service proxy = (Service) Proxy.newProxyInstance(realService.getClass().getClassLoader(),
                                                         new Class<?>[]{Service.class},
                                                         handler);
        proxy.performOperation();
    }
}

3. CGLIB代理

CGLIB代理是通过继承目标对象的方式来创建代理类。它是第三方库(如Spring AOP)常用的一种代理方式,适用于没有实现接口的类。

优点:

  • 不需要目标对象实现接口,可以代理任何类。

缺点:

  • 由于采用了继承的方式,目标类不能是final类,代理类也不能是final方法。
  • 相对于JDK动态代理,CGLIB代理的性能较高,但由于使用了字节码生成技术,可能会增加复杂性。

 CGLIB代理模式类图:

 示例代码:

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

// 目标对象
public class RealService {
    public void performOperation() {
        System.out.println("Performing operation in RealService");
    }
}

// CGLIB代理
public class CglibProxy implements MethodInterceptor {
    private Object target;

    public CglibProxy(Object target) {
        this.target = target;
    }

    public Object createProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Proxy: Before operation");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("Proxy: After operation");
        return result;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        RealService realService = new RealService();
        CglibProxy proxy = new CglibProxy(realService);
        RealService proxyService = (RealService) proxy.createProxy();
        proxyService.performOperation();
    }
}

三、代理模式的应用场景

代理模式在实际开发中有很多应用场景,包括但不限于以下几种:

  1. 远程代理:为一个对象在不同地址空间提供局部代表,以便隐藏实际对象存在于不同地址空间的事实。
  2. 虚拟代理:根据需要创建开销大的对象,通过代理对象来控制对真实对象的访问。
  3. 安全代理:控制真实对象的访问权限,确保用户只能进行允许的操作。
  4. 智能引用代理:在访问对象时执行一些附加操作,如记录访问日志、统计访问次数等。

四、总结

代理模式通过引入代理对象,在不修改原始对象的情况下,为其添加额外的功能或控制。无论是静态代理、动态代理还是CGLIB代理,它们都有各自的优缺点,开发者可以根据具体的需求选择合适的代理方式。

希望本文能帮助你更好地理解代理模式,并在实际项目中灵活应用。如果你有任何问题或建议,欢迎在评论区留言讨论!

 

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值