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

静态代理

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毫秒

总结

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

相关推荐
会敲代码的小张12 小时前
设计模式-观察者模式
java·开发语言·后端·观察者模式·设计模式·代理模式
OkeyProxy3 天前
如何在安卓設備上更換IP地址?
代理模式·proxy模式·ip地址·代理ip·全局代理
丶白泽4 天前
重修设计模式-结构型-代理模式
设计模式·系统安全·代理模式
coffee_baby4 天前
深入解析代理模式:静态代理、JDK 动态代理和 CGLIB 的全方位对比!
java·代理模式
攸攸太上5 天前
Java面试题·解释题·单例模式、工厂模式、代理模式部分
java·学习·单例模式·代理模式·简单工厂模式
qq_535246145 天前
代码随想录 第九章 动态规划part03 01背包问题 一维 416. 分割等和子集
算法·动态规划·代理模式
weixin_531804247 天前
请解释Java中的深拷贝和浅拷贝的区别。什么是Java中的代理模式?它有什么作用?
java·开发语言·代理模式
AI让世界更懂你7 天前
漫谈设计模式 [11]:代理模式
python·设计模式·代理模式
W Y7 天前
【架构设计模式-1】代理模式
安全·系统安全·代理模式