代理模式详解:静态代理与动态代理的实现

静态代理

eg: 我们在商店买商品,而商店的商品又来源于厂商,此时商店的作用便是代理

1. 定义服务接口

java 复制代码
public interface UserService {
    void select();
    void update();
}

2. 实现服务接口的类

java 复制代码
public class UserServiceImpl implements UserService {
    @Override
    public void select() {
        System.out.println("这是查找");
    }

    @Override
    public void update() {
        System.out.println("这是修改");
    }
}

3. 创建代理类

代理类同样实现 UserService 接口,并在其中添加扩展逻辑。

java 复制代码
public class UserServiceProxy implements UserService {
    private UserServiceImpl userService = new UserServiceImpl();

    @Override
    public void select() {
        long begin = System.currentTimeMillis();
        userService.select();
        long end = System.currentTimeMillis();
        System.out.println("select执行时间为" + (end - begin) + "毫秒");
    }

    @Override
    public void update() {
        long begin = System.currentTimeMillis();
        userService.update();
        long end = System.currentTimeMillis();
        System.out.println("update执行时间为" + (end - begin) + "毫秒");
    }
}

静态代理的问题

虽然静态代理允许我们在不修改原有业务逻辑代码的情况下添加额外逻辑,但它也存在以下缺点:

  1. 代理类数量繁多:当有多个目标类时,需要为每个目标类创建对应的代理类,导致代理类数量激增。
  2. 耦合度高:如果在接口中增加或修改功能,需要同时修改实现类和代理类,降低了代码的灵活性。

动态代理

动态代理利用 JDK 的反射机制,能够在运行时创建代理对象,避免了静态代理的缺点。

动态代理的实现方式

  • 基于jdk的动态代理:使用java反射技术实现(主要有invocatoionHandler接口,Method和Proxy类)
  • 基于cglib动态代理:cglib为第三方的工具库,主要用来创建代理对象。目标类只需要继承cglib生成一个被代理对象的子类作为代理(核心为:MethodIntercepter接口和Enhancer类)

注意:基于jdk动态代理必须要实现接口,若是没有实现接口则使用cglib来创建动态代理

其中:

  1. Method类:
  • method表示代理所调用的目标方法
  1. Proxy类
  • 通过该类可以生成代理对象,代理对象的创建是由jdk提供的,我们只是负责调Proxy类中的方法来拿到这个代理对象
  • 调用Proxy类中的静态方法newProxyInstance()来创建一个代理对象
java 复制代码
  public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
  • newProxyInstance参数说明:
    • loader表示目标对象的类加载器,固定写法:目标对象.getClass().getClassLoader();
    • interfaces表示目标对象所实现的接口,接口多继承,因此是个数组。固定写法:目标对象.getClass().getInterface();
    • h表示代理类所要完成的功能
      返回值就是代理类对象,并且在该对象创建时已经说明了,该代理类对象所代理的目标对象是谁,该目标对象完成了那些功能,该代理类所要完成的功能

JDK 动态代理的步骤

  1. 定义被代理的接口
java 复制代码
public interface OrderService {
    void create();
}
  1. 实现被代理接口的类
java 复制代码
public class OrderServiceImpl implements OrderService {
    @Override
    public void create() {
        System.out.println("执行创建订单");
    }
}
  1. 创建代理类并实现 InvocationHandler 接口
java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class PerformanceInvocationHandler implements InvocationHandler {
    private Object real;

    public PerformanceInvocationHandler(Object real) {
        this.real = real;
    }

   /**
     * @param proxy  代理对象
     * @param method 当前执行的方法对象
     * @param args   参数列表
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long begin = System.currentTimeMillis();
        Object result = method.invoke(real, args);
        long end = System.currentTimeMillis();
        System.out.println("执行方法耗时" + (end - begin) + "毫秒");
        return result;
    }
}
  1. 测试动态代理
java 复制代码
import java.lang.reflect.Proxy;

public class Test01 {
    public static void main(String[] args) {
        // 创建被代理对象
        OrderServiceImpl orderService = new OrderServiceImpl();
        
        // 获取类加载器
        ClassLoader classLoader = orderService.getClass().getClassLoader();
        
        // 获取接口
        Class<?>[] interfaces = orderService.getClass().getInterfaces();
        
        // 创建 InvocationHandler
        PerformanceInvocationHandler handler = new PerformanceInvocationHandler(orderService);
        
        // 创建动态代理对象
        OrderService orderServiceProxy = (OrderService) Proxy.newProxyInstance(classLoader, interfaces, handler);
        
        // 调用代理的方法
        orderServiceProxy.create();
    }
}

输出结果

复制代码
执行创建订单
执行方法耗时1毫秒

总结

通过使用静态代理和动态代理模式,我们能够有效地扩展对象的功能而无需修改原有业务逻辑。尽管静态代理适用于简单场景,但随着系统的复杂性增加,动态代理提供了更高的灵活性和可扩展性,尤其是在处理多个目标对象时。

相关推荐
故渊at5 天前
系列一:架构思想进阶 | 第3篇 SOLID 原则与设计模式实战:从“代码搬运工”到“架构师”的必经之路
观察者模式·设计模式·重构·架构·代理模式
basketball6166 天前
设计模式入门:5. 代理模式详解 C++实现
c++·设计模式·代理模式
2601_961194026 天前
2026初级会计经济法基础知识点汇总
python·django·pdf·virtualenv·代理模式·pygame
2601_961194026 天前
考研模拟卷谁的比较好|27李林合工大肖四肖八数学英语408PDF
考研·elasticsearch·全文检索·代理模式·lucene·桥接模式·访问者模式
Rick19938 天前
代理模式 vs 适配器模式
代理模式·适配器模式
老码观察10 天前
设计模式实战解读(八):代理模式——控制访问的隐形中间层
设计模式·代理模式
青山师11 天前
动态规划算法深度解析:从状态转移方程到工业级优化
数据结构·算法·面试·动态规划·代理模式·java面试
Yana.nice15 天前
nginx的四种代理模式
运维·nginx·代理模式
陈辛chenxin15 天前
【数据挖掘01】相似度算法大全(万字讲解)
算法·数据挖掘·代理模式