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

静态代理

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

总结

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

相关推荐
肘击鸣的百k路4 小时前
Java 代理模式详解
java·开发语言·代理模式
OkeyProxy16 小时前
怎麼解決IP地址衝突的問題?
代理模式·proxy模式·ip地址·代理服务器·海外ip代理
G皮T4 天前
【设计模式】结构型模式(二):代理模式
java·设计模式·编程·代理模式·proxy pattern·结构型模式
zzzhpzhpzzz4 天前
设计模式——代理模式
设计模式·系统安全·代理模式
羽愿5 天前
技术总结(十九)
代理模式
__Black_Opium__5 天前
设计模式 - 代理模式
设计模式·代理模式
OkeyProxy6 天前
路由器中怎麼設置代理IP?
代理模式·路由器·proxy模式·代理服务器·海外ip代理
decode126 天前
代码随想录算法训练营第三十二天 | 动态规划理论基础 509.斐波那契数 70.爬楼梯 746.使用最小花费爬楼梯
算法·动态规划·代理模式
收破烂的小熊猫~6 天前
动态规划(基础版)70.爬楼梯
算法·动态规划·代理模式
金池尽干7 天前
设计模式之——代理模式
c++·设计模式·代理模式