Java设计模式之代理模式(Proxy)深度解析

目录

  • [1. 模式概述](#1. 模式概述)
  • [2. 模式结构](#2. 模式结构)
    • [2.1 UML类图](#2.1 UML类图)
    • [2.2 核心角色说明](#2.2 核心角色说明)
  • [3. 代理模式实现机制](#3. 代理模式实现机制)
    • [3.1 静态代理:编译时织入](#3.1 静态代理:编译时织入)
    • [3.2 动态代理:运行时织入](#3.2 动态代理:运行时织入)
      • [3.2.1 JDK动态代理(基于接口)](#3.2.1 JDK动态代理(基于接口))
      • [3.2.2 CGLIB 动态代理(基于继承)](#3.2.2 CGLIB 动态代理(基于继承))
    • [3.3 代理模式对比分析](#3.3 代理模式对比分析)
  • [4. Spring AOP 中的代理实现](#4. Spring AOP 中的代理实现)
    • [4.1 Spring代理机制概述](#4.1 Spring代理机制概述)
    • [4.2 代理选择策略](#4.2 代理选择策略)
    • [4.3 切面定义与实现](#4.3 切面定义与实现)
  • [5. 模式的优劣分析](#5. 模式的优劣分析)
    • [5.1 优点](#5.1 优点)
    • [5.2 缺点](#5.2 缺点)
  • [6. 代理模式的应用场景](#6. 代理模式的应用场景)
    • [6.1 典型应用场景](#6.1 典型应用场景)
      • [6.1.1 权限控制与安全代理](#6.1.1 权限控制与安全代理)
      • [6.1.2 延迟加载代理(Lazy Loading)](#6.1.2 延迟加载代理(Lazy Loading))
      • [6.1.3 远程代理(RPC框架)](#6.1.3 远程代理(RPC框架))
      • [6.1.4 缓存代理](#6.1.4 缓存代理)
      • [6.1.5 智能引用代理](#6.1.5 智能引用代理)
    • [6.2 企业级应用案例](#6.2 企业级应用案例)
  • [7. 代理模式的最佳实践](#7. 代理模式的最佳实践)
    • [7.1 设计原则](#7.1 设计原则)
    • [7.2 性能优化策略](#7.2 性能优化策略)
    • [7.3 安全实践](#7.3 安全实践)
  • 8.代理模式与其他模式对比
    • [8.1 代理 vs 装饰器模式](#8.1 代理 vs 装饰器模式)
    • [8.2 代理 vs 适配器模式](#8.2 代理 vs 适配器模式)
  • 9.总结与进阶思考
    • [9.1 核心总结](#9.1 核心总结)
    • [9.2 进阶思考](#9.2 进阶思考)

1. 模式概述

代理模式(Proxy Pattern) 是一种结构型设计模式,通过创建代理对象 控制对真实对象的访问。代理对象充当真实对象的替身,在客户端和真实对象之间引入间接层,实现访问控制、功能增强等目的。这种模式的核心价值在于:

  • 访问控制:限制对敏感对象的直接访问
  • 功能增强:在不修改原始对象的情况下添加新功能
  • 延迟加载:优化资源使用,按需创建昂贵对象
  • 简化接口:为复杂系统提供更简洁的访问接口

客户端 代理对象 真实对象

代理模式在企业级开发中应用广泛,如Spring AOP中的事务管理、MyBatis的Mapper接口代理、远程方法调用(RPC)等场景。它遵循开放封闭原则,通过代理类扩展功能而非修改原有类,提高了系统的灵活性和可维护性。

2. 模式结构

2.1 UML类图

<<interface>> Subject +request() : void RealSubject +request() : void Proxy -realSubject: RealSubject +request() : void Client +main() : void

2.2 核心角色说明

角色 职责 实现要点 设计原则
Subject 定义真实主题和代理主题的共同接口 使用接口或抽象类定义 接口隔离原则
RealSubject 实际执行业务逻辑的真实对象 包含核心业务逻辑实现 单一职责原则
Proxy 控制对真实主题的访问,提供额外功能 持有真实主题的引用 开闭原则
Client 通过代理对象间接访问真实主题 无需知道代理存在 迪米特法则

这种结构分离了核心功能附加功能,符合单一职责原则,使得系统更易于扩展和维护。

3. 代理模式实现机制

3.1 静态代理:编译时织入

静态代理是在编译期就已经确定代理关系的实现方式。需要为每个被代理的类创建一个代理类,代理类和目标类实现相同的接口,代理类持有目标类的引用,并在调用目标方法前后执行增强逻辑。

核心特点

  • 编译期确定:代理关系在编译时就已经确定
  • 一对一关系:一个代理类对应一个目标类
  • 代码冗余:需要为每个目标类编写代理类
  • 类型安全:编译期检查,类型安全

实现原理

  • 代理类和真实类实现相同接口
  • 代理类持有真实类的引用
  • 在代理类方法中添加额外逻辑

适用场景

  • 简单场景:代理逻辑固定且简单的场景
  • 性能敏感:对性能要求极高,不能接受动态代理的开销
  • 编译期检查:需要严格的编译期类型检查
  • 小型项目:项目规模较小,代理类数量可控
java 复制代码
// 1. 定义服务接口
interface PaymentService {
    void processPayment(double amount);
}

// 2. 真实服务实现
class RealPaymentService implements PaymentService {
    @Override
    public void processPayment(double amount) {
        System.out.println("处理支付: $" + amount);
    }
}

// 3. 静态代理类
class PaymentProxy implements PaymentService {
    private final PaymentService realService;
    
    public PaymentProxy() {
        this.realService = new RealPaymentService();
    }
    
    @Override
    public void processPayment(double amount) {
        // 前置增强:验证
        validatePayment(amount);
        logPayment(amount);
        
        // 委托真实对象
        realService.processPayment(amount);
        
        // 后置增强:通知
        sendNotification();
    }
    
    private void validatePayment(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("金额必须大于0");
    }
    
    private void logPayment(double amount) {
        System.out.println("[LOG] 支付请求: $" + amount);
    }
    
    private void sendNotification() {
        System.out.println("[NOTIFY] 支付成功通知已发送");
    }
}

// 4. 客户端使用
public class Client {
    public static void main(String[] args) {
        PaymentService service = new PaymentProxy();
        service.processPayment(150.0);
    }
}

静态代理优缺点分析

优点 缺点
✅ 编译期检查,类型安全 ❌ 每个服务类需要创建代理类
✅ 性能接近直接调用 ❌ 接口变更需修改代理类
✅ 逻辑清晰,易于理解 ❌ 代理类数量随服务类增加
✅ 支持方法级控制 ❌ 灵活性不足

3.2 动态代理:运行时织入

3.2.1 JDK动态代理(基于接口)

JDK动态代理基于接口反射 机制,在运行时动态生成代理类。通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口实现,要求被代理对象必须实现至少一个接口。

实现原理

  • 代理类生成:在运行时通过字节码技术生成代理类
  • 接口代理:只能代理接口,不能代理类
  • 反射调用:通过反射机制调用目标方法
  • 处理器机制:通过InvocationHandler统一处理所有方法调用

JDK动态代理特点

  • 只能代理实现了接口的类
  • 运行时生成代理类,减少编码量
  • 通过反射调用方法,有一定性能开销
  • 适合代理接口定义明确的服务
java 复制代码
import java.lang.reflect.*;

// 1. 调用处理器(性能监控)
class PerformanceMonitor implements InvocationHandler {
    private final Object target;
    private final Map<String, MethodStats> statsMap = new ConcurrentHashMap<>();
    
    public PerformanceMonitor(Object target) {
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.nanoTime();
        
        // 调用真实方法
        Object result = method.invoke(target, args);
        
        long duration = System.nanoTime() - start;
        recordMethodStats(method, duration);
        return result;
    }
    
    private void recordMethodStats(Method method, long duration) {
        String methodName = method.getName();
        statsMap.compute(methodName, (k, v) -> {
            if (v == null) return new MethodStats(methodName, duration);
            v.addExecution(duration);
            return v;
        });
    }
    
    public void printStats() {
        System.out.println("\n===== 方法性能统计 =====");
        statsMap.values().forEach(System.out::println);
    }
    
    static class MethodStats {
        private final String methodName;
        private long count;
        private long totalTime;
        private long maxTime;
        
        public MethodStats(String methodName, long initialTime) {
            this.methodName = methodName;
            addExecution(initialTime);
        }
        
        public void addExecution(long time) {
            count++;
            totalTime += time;
            if (time > maxTime) maxTime = time;
        }
        
        @Override
        public String toString() {
            return String.format("%s: 调用次数=%d, 平均耗时=%.2fms, 最大耗时=%.2fms",
                methodName, count, 
                (totalTime / 1_000_000.0) / count,
                maxTime / 1_000_000.0);
        }
    }
}

// 2. 客户端使用
public class DynamicProxyClient {
    public static void main(String[] args) {
        // 创建真实对象
        DatabaseService realService = new RealDatabaseService();
        
        // 创建动态代理
        DatabaseService proxy = (DatabaseService) Proxy.newProxyInstance(
            DatabaseService.class.getClassLoader(),
            new Class[]{DatabaseService.class},
            new PerformanceMonitor(realService)
        );
        
        // 通过代理调用
        for (int i = 0; i < 5; i++) {
            proxy.executeQuery("SELECT * FROM table_" + i);
        }
        
        // 打印性能统计
        ((PerformanceMonitor) Proxy.getInvocationHandler(proxy)).printStats();
    }
}

JDK动态代理优缺点分析

优点 缺点
✅ 一个处理器可以代理多个接口 ❌ 只能代理接口,不能代理类
✅ 减少类数量,避免类爆炸 ❌ 反射调用有性能开销(现代JVM已优化)
✅ 灵活性高,可以动态添加功能 ❌ 内部方法调用不会被代理
✅ 与Java标准库集成,无需额外依赖 ❌ 接口方法必须是public

性能优化建议

  1. 缓存代理类:重复创建代理类开销大,应该缓存
  2. 避免过度代理:只在必要时使用代理
  3. 使用Method对象缓存:避免重复获取Method对象
  4. 考虑使用字节码增强:对性能要求极高的场景

3.2.2 CGLIB 动态代理(基于继承)

CGLIB(Code Generation Library)通过字节码增强技术生成目标类的子类作为代理,不需要接口支持。CGLIB是一个强大的高性能代码生成库,它通过继承目标类并重写方法来实现代理。与JDK动态代理不同,CGLIB不需要目标类实现接口。

核心机制

  1. 字节码生成:在运行时通过ASM字节码框架生成目标类的子类
  2. 方法拦截:通过MethodInterceptor接口拦截方法调用
  3. FastClass机制:避免反射调用,提高性能
  4. 回调过滤器:支持对不同方法使用不同的拦截策略

实现原理

  • 使用Enhancer类创建代理
  • 实现MethodInterceptor接口处理调用
  • 生成目标类的子类作为代理类

依赖配置

xml 复制代码
<!-- Maven依赖 -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

代码实现

java 复制代码
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * CGLIB动态代理实现
 * 方法拦截器示例
 */
public class CglibMethodInterceptor implements MethodInterceptor {
    
    // 目标对象
    private final Object target;
    
    public CglibMethodInterceptor(Object target) {
        this.target = target;
    }
    
    /**
     * 创建代理对象
     * @param target 目标对象
     * @return 代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target) {
        Enhancer enhancer = new Enhancer();
        
        // 设置父类(目标类)
        enhancer.setSuperclass(target.getClass());
        
        // 设置回调(拦截器)
        enhancer.setCallback(new CglibMethodInterceptor(target));
        
        // 设置回调过滤器(可选)
        enhancer.setCallbackFilter(method -> {
            // 对不同的方法使用不同的拦截策略
            if (method.getName().startsWith("get")) {
                return 0; // 使用第一个回调
            } else {
                return 0; // 默认使用第一个回调
            }
        });
        
        // 创建代理对象
        return (T) enhancer.create();
    }
    
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        String methodName = method.getName();
        
        // 过滤Object类的方法(如toString、hashCode等)
        if (method.getDeclaringClass() == Object.class) {
            return proxy.invokeSuper(obj, args);
        }
        
        // 前置增强
        System.out.println("[CGLIB代理] 开始执行方法: " + methodName);
        System.out.println("[CGLIB代理] 参数: " + (args != null ? Arrays.toString(args) : "无"));
        
        long startTime = System.nanoTime();
        Object result = null;
        
        try {
            // 调用目标方法
            // 注意:这里使用invokeSuper调用父类(目标类)方法
            // 使用invoke会递归调用代理方法,导致栈溢出
            result = proxy.invokeSuper(obj, args);
            
            // 返回结果增强
            if (result instanceof String) {
                result = "[CGLIB增强] " + result;
            }
            
            // 后置增强
            System.out.println("[CGLIB代理] 方法执行成功: " + methodName);
            System.out.println("[CGLIB代理] 返回值: " + result);
            
        } catch (Exception e) {
            // 异常增强
            System.err.println("[CGLIB代理] 方法执行失败: " + methodName);
            System.err.println("[CGLIB代理] 异常信息: " + e.getMessage());
            throw e;
        } finally {
            // 最终增强
            long endTime = System.nanoTime();
            System.out.println("[CGLIB代理] 方法执行耗时: " + (endTime - startTime) + "ns");
        }
        
        return result;
    }
}

高级特性实现

java 复制代码
import net.sf.cglib.proxy.*;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 增强型CGLIB代理
 * 支持多回调、性能监控等高级功能
 */
public class EnhancedCglibProxy {
    
    private static final ConcurrentHashMap<Class<?>, Object> PROXY_CACHE = new ConcurrentHashMap<>();
    private static final AtomicInteger PROXY_COUNTER = new AtomicInteger(0);
    
    /**
     * 创建带缓存的代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T createCachedProxy(T target) {
        Class<?> targetClass = target.getClass();
        
        // 检查缓存
        if (PROXY_CACHE.containsKey(targetClass)) {
            return (T) PROXY_CACHE.get(targetClass);
        }
        
        // 创建代理
        T proxy = createProxy(target);
        
        // 加入缓存
        PROXY_CACHE.put(targetClass, proxy);
        
        return proxy;
    }
    
    /**
     * 创建多回调代理
     */
    @SuppressWarnings("unchecked")
    public static <T> T createMultiCallbackProxy(T target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        
        // 设置多个回调
        Callback[] callbacks = new Callback[] {
            new LoggingInterceptor(target),      // 日志拦截
            new SecurityInterceptor(target),     // 安全拦截
            new PerformanceInterceptor(target),  // 性能监控
            NoOp.INSTANCE                        // 直接调用,不拦截
        };
        
        enhancer.setCallbacks(callbacks);
        
        // 设置回调过滤器
        enhancer.setCallbackFilter(method -> {
            String methodName = method.getName();
            
            if (methodName.startsWith("get") || methodName.startsWith("query")) {
                return 0; // 使用日志拦截
            } else if (methodName.startsWith("add") || methodName.startsWith("update")) {
                return 1; // 使用安全拦截
            } else if (methodName.startsWith("delete")) {
                return 2; // 使用性能监控
            } else {
                return 3; // 直接调用
            }
        });
        
        return (T) enhancer.create();
    }
    
    // 各种拦截器实现
    static class LoggingInterceptor implements MethodInterceptor {
        private final Object target;
        
        LoggingInterceptor(Object target) {
            this.target = target;
        }
        
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("[日志] 开始执行: " + method.getName());
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("[日志] 执行完成: " + method.getName());
            return result;
        }
    }
    
    static class SecurityInterceptor implements MethodInterceptor {
        private final Object target;
        
        SecurityInterceptor(Object target) {
            this.target = target;
        }
        
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("[安全] 权限检查...");
            // 实际权限检查逻辑
            return proxy.invokeSuper(obj, args);
        }
    }
    
    static class PerformanceInterceptor implements MethodInterceptor {
        private final Object target;
        
        PerformanceInterceptor(Object target) {
            this.target = target;
        }
        
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            long startTime = System.nanoTime();
            Object result = proxy.invokeSuper(obj, args);
            long endTime = System.nanoTime();
            System.out.println("[性能] 方法耗时: " + (endTime - startTime) + "ns");
            return result;
        }
    }
    
    @SuppressWarnings("unchecked")
    private static <T> T createProxy(T target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new CglibMethodInterceptor(target));
        return (T) enhancer.create();
    }
}

使用示例

java 复制代码
/**
 * 不需要接口的普通类
 */
public class OrderService {
    
    public void createOrder(String orderId, String productName) {
        System.out.println("创建订单: " + orderId + ", 产品: " + productName);
        // 模拟业务逻辑
        try {
            Thread.sleep(100); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    public String getOrderStatus(String orderId) {
        System.out.println("查询订单状态: " + orderId);
        return "订单状态: 已发货";
    }
    
    public void cancelOrder(String orderId) {
        System.out.println("取消订单: " + orderId);
        throw new RuntimeException("订单取消失败: 已发货状态不能取消");
    }
    
    // final方法不会被代理
    public final String getServiceName() {
        return "OrderService";
    }
    
    // private方法不会被代理
    private void internalProcess() {
        System.out.println("内部处理逻辑");
    }
}

/**
 * CGLIB动态代理测试
 */
public class CglibProxyDemo {
    
    public static void main(String[] args) {
        System.out.println("=== CGLIB动态代理测试 ===");
        
        // 创建目标对象(不需要接口)
        OrderService realService = new OrderService();
        
        // 创建基本代理
        System.out.println("\n1. 测试基本CGLIB代理:");
        OrderService basicProxy = CglibMethodInterceptor.createProxy(realService);
        
        System.out.println("测试创建订单:");
        basicProxy.createOrder("ORD001", "Java编程思想");
        
        System.out.println("\n测试查询订单状态:");
        String status = basicProxy.getOrderStatus("ORD001");
        System.out.println("增强后的状态: " + status);
        
        System.out.println("\n测试取消订单(异常处理):");
        try {
            basicProxy.cancelOrder("ORD001");
        } catch (Exception e) {
            System.err.println("捕获到异常: " + e.getMessage());
        }
        
        // 测试final方法
        System.out.println("\n测试final方法(不会被代理):");
        String serviceName = basicProxy.getServiceName();
        System.out.println("服务名称: " + serviceName);
        
        // 验证代理类型
        System.out.println("\n2. 代理类型信息:");
        System.out.println("代理类: " + basicProxy.getClass().getName());
        System.out.println("父类: " + basicProxy.getClass().getSuperclass().getName());
        System.out.println("是OrderService的子类: " + OrderService.class.isAssignableFrom(basicProxy.getClass()));
        
        // 测试缓存代理
        System.out.println("\n3. 测试缓存代理:");
        OrderService cachedProxy1 = EnhancedCglibProxy.createCachedProxy(realService);
        OrderService cachedProxy2 = EnhancedCglibProxy.createCachedProxy(realService);
        System.out.println("两次获取的缓存代理是同一个对象: " + (cachedProxy1 == cachedProxy2));
        
        // 测试多回调代理
        System.out.println("\n4. 测试多回调代理:");
        OrderService multiCallbackProxy = EnhancedCglibProxy.createMultiCallbackProxy(realService);
        
        System.out.println("测试查询方法(使用日志拦截):");
        multiCallbackProxy.getOrderStatus("ORD002");
        
        System.out.println("\n测试创建方法(使用安全拦截):");
        multiCallbackProxy.createOrder("ORD002", "设计模式");
        
        System.out.println("\n测试删除方法(使用性能监控):");
        try {
            multiCallbackProxy.cancelOrder("ORD002");
        } catch (Exception e) {
            System.err.println("预期异常: " + e.getMessage());
        }
    }
}

限制与注意事项

  1. final类和方法:CGLIB无法代理final类和方法
  2. 构造函数:代理类会调用父类的无参构造函数,目标类需要有可访问的无参构造
  3. private方法:private方法不会被代理
  4. static方法:static方法不会被代理
  5. 性能考虑:虽然CGLIB避免了反射,但字节码生成也有开销

3.3 代理模式对比分析

特性 静态代理 JDK动态代理 CGLIB代理
实现方式 手动编码 反射API 字节码增强
代理目标 具体类 接口
性能
依赖 Java标准库 CGLIB库
限制 需预定义代理类 目标需实现接口 无法代理final类
适用场景 简单系统 接口代理 类代理/复杂系统

4. Spring AOP 中的代理实现

4.1 Spring代理机制概述

Spring框架通过代理模式实现了AOP(面向切面编程)的核心功能。Spring根据目标对象是否实现接口,自动选择JDK动态代理或CGLIB代理。

4.2 代理选择策略

Spring的代理选择遵循以下规则:

  1. 如果目标对象实现了接口:默认使用JDK动态代理
  2. 如果目标对象没有实现接口:使用CGLIB代理
  3. 强制使用CGLIB:@EnableAspectJAutoProxy(proxyTargetClass=true)
  4. 代理模式优化:@EnableAspectJAutoProxy(exposeProxy=true)

4.3 切面定义与实现

java 复制代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.util.Arrays;

/**
 * 日志切面
 * 记录方法执行日志和性能监控
 */
@Aspect
@Component
public class LoggingAspect {
    
    private static final org.slf4j.Logger logger = 
        org.slf4j.LoggerFactory.getLogger(LoggingAspect.class);
    
    /**
     * 定义切入点:所有Service层的方法
     */
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}
    
    /**
     * 定义切入点:所有Controller层的方法
     */
    @Pointcut("execution(* com.example.controller.*.*(..))")
    public void controllerLayer() {}
    
    /**
     * 定义切入点:所有Mapper接口的方法
     */
    @Pointcut("execution(* com.example.mapper.*.*(..))")
    public void mapperLayer() {}
    
    /**
     * 前置通知:在方法执行前记录日志
     */
    @Before("serviceLayer()")
    public void logBefore(JoinPoint joinPoint) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        
        logger.info("开始执行方法: {}.{}", className, methodName);
        logger.info("方法参数: {}", Arrays.toString(args));
    }
    
    /**
     * 后置通知:在方法正常返回后记录日志
     */
    @AfterReturning(
        pointcut = "serviceLayer()",
        returning = "result"
    )
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        
        logger.info("方法执行成功: {}.{}", className, methodName);
        logger.info("返回结果: {}", result);
    }
    
    /**
     * 异常通知:在方法抛出异常后记录日志
     */
    @AfterThrowing(
        pointcut = "serviceLayer()",
        throwing = "error"
    )
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        
        logger.error("方法执行异常: {}.{}", className, methodName);
        logger.error("异常信息: {}", error.getMessage(), error);
    }
    
    /**
     * 最终通知:在方法执行完成后记录日志
     */
    @After("serviceLayer()")
    public void logAfter(JoinPoint joinPoint) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        
        logger.info("方法执行完成: {}.{}", className, methodName);
    }
    
    /**
     * 环绕通知:性能监控和异常处理
     */
    @Around("serviceLayer()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        logger.info("环绕通知 - 开始执行方法: {}.{}", className, methodName);
        
        try {
            // 执行目标方法
            Object result = joinPoint.proceed();
            
            stopWatch.stop();
            
            logger.info("环绕通知 - 方法执行成功: {}.{}", className, methodName);
            logger.info("方法执行耗时: {} ms", stopWatch.getTotalTimeMillis());
            
            return result;
            
        } catch (Exception e) {
            stopWatch.stop();
            
            logger.error("环绕通知 - 方法执行失败: {}.{}", className, methodName);
            logger.error("执行耗时: {} ms", stopWatch.getTotalTimeMillis());
            logger.error("异常类型: {}", e.getClass().getSimpleName());
            logger.error("异常信息: {}", e.getMessage());
            
            throw e;
        }
    }
    
    /**
     * 事务管理切面
     */
    @Around("@annotation(org.springframework.transaction.annotation.Transactional)")
    public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("开始事务管理...");
        
        try {
            Object result = joinPoint.proceed();
            logger.info("事务提交成功");
            return result;
            
        } catch (Exception e) {
            logger.error("事务回滚,原因: {}", e.getMessage());
            throw e;
        }
    }
    
    /**
     * 缓存切面
     */
    @Around("@annotation(com.example.annotation.Cacheable)")
    public Object manageCache(ProceedingJoinPoint joinPoint) throws Throwable {
        String cacheKey = generateCacheKey(joinPoint);
        
        // 尝试从缓存获取
        Object cachedValue = getFromCache(cacheKey);
        if (cachedValue != null) {
            logger.info("缓存命中: {}", cacheKey);
            return cachedValue;
        }
        
        logger.info("缓存未命中,执行目标方法");
        Object result = joinPoint.proceed();
        
        // 缓存结果
        saveToCache(cacheKey, result);
        logger.info("结果已缓存: {}", cacheKey);
        
        return result;
    }
    
    private String generateCacheKey(JoinPoint joinPoint) {
        StringBuilder keyBuilder = new StringBuilder();
        keyBuilder.append(joinPoint.getTarget().getClass().getSimpleName());
        keyBuilder.append(".").append(joinPoint.getSignature().getName());
        
        Object[] args = joinPoint.getArgs();
        if (args != null && args.length > 0) {
            for (Object arg : args) {
                keyBuilder.append(".").append(arg != null ? arg.hashCode() : "null");
            }
        }
        
        return keyBuilder.toString();
    }
    
    private Object getFromCache(String key) {
        // 实际项目中会从Redis等缓存获取
        return null;
    }
    
    private void saveToCache(String key, Object value) {
        // 实际项目中会保存到Redis等缓存
    }
}

最佳实践建议:

  1. 合理选择代理类型:根据目标对象特性选择JDK或CGLIB代理
  2. 避免过度使用AOP:只在横切关注点使用,避免影响核心逻辑
  3. 注意代理范围:Spring默认只代理public方法
  4. 处理内部调用问题 :使用AopContext.currentProxy()解决内部调用
  5. 性能监控:对关键业务方法添加性能监控切面

5. 模式的优劣分析

5.1 优点

  1. 职责清晰:真实对象专注核心逻辑,代理处理附加功能
  2. 高扩展性:在不修改原始对象的情况下增加新功能
  3. 访问控制:代理对象控制对真实对象的访问权限
  4. 性能优化:实现延迟加载、缓存等优化手段
  5. 解耦合:客户端与真实对象解耦,提高系统灵活性
  6. 开闭原则:通过代理扩展功能,无需修改原有类

5.2 缺点

  1. 系统复杂度增加:引入额外抽象层,增加理解难度
  2. 性能开销:代理调用增加处理时间(特别是反射)
  3. 实现复杂度:动态代理涉及反射和字节码技术
  4. 类文件增多:静态代理导致类数量膨胀
  5. 调试困难:动态代理堆栈信息复杂,增加调试难度

6. 代理模式的应用场景

6.1 典型应用场景

6.1.1 权限控制与安全代理

场景描述:

在企业管理系统中,不同角色的用户对系统资源的访问权限不同。需要实现细粒度的权限控制,确保只有授权用户才能执行特定操作。

实现方案:

java 复制代码
import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.util.Set;

/**
 * 权限控制代理实现
 */
public class SecurityProxy implements java.lang.reflect.InvocationHandler {
    
    private final Object target;
    private final SecurityContext securityContext;
    
    public SecurityProxy(Object target, SecurityContext securityContext) {
        this.target = target;
        this.securityContext = securityContext;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 检查方法级别的权限注解
        RequiredPermission permission = method.getAnnotation(RequiredPermission.class);
        
        if (permission != null) {
            String requiredPermission = permission.value();
            String requiredRole = permission.role();
            
            // 检查权限
            if (!hasPermission(requiredPermission)) {
                throw new SecurityException("权限不足,需要权限: " + requiredPermission);
            }
            
            // 检查角色
            if (!requiredRole.isEmpty() && !hasRole(requiredRole)) {
                throw new SecurityException("角色不符,需要角色: " + requiredRole);
            }
        }
        
        // 检查类级别的权限注解
        Class<?> targetClass = target.getClass();
        if (targetClass.isAnnotationPresent(Secured.class)) {
            Secured secured = targetClass.getAnnotation(Secured.class);
            String[] allowedRoles = secured.value();
            
            if (!hasAnyRole(allowedRoles)) {
                throw new SecurityException("访问被拒绝,需要以下角色之一: " + 
                    String.join(", ", allowedRoles));
            }
        }
        
        // 记录审计日志
        auditLog(method, args);
        
        // 执行目标方法
        return method.invoke(target, args);
    }
    
    private boolean hasPermission(String permission) {
        Set<String> userPermissions = securityContext.getCurrentUserPermissions();
        return userPermissions.contains(permission);
    }
    
    private boolean hasRole(String role) {
        Set<String> userRoles = securityContext.getCurrentUserRoles();
        return userRoles.contains(role);
    }
    
    private boolean hasAnyRole(String[] roles) {
        Set<String> userRoles = securityContext.getCurrentUserRoles();
        for (String role : roles) {
            if (userRoles.contains(role)) {
                return true;
            }
        }
        return false;
    }
    
    private void auditLog(Method method, Object[] args) {
        String username = securityContext.getCurrentUsername();
        String className = target.getClass().getSimpleName();
        String methodName = method.getName();
        
        AuditLogger.log(
            "用户: " + username + 
            " 执行: " + className + "." + methodName +
            " 参数: " + formatArgs(args)
        );
    }
    
    private String formatArgs(Object[] args) {
        if (args == null || args.length == 0) {
            return "[]";
        }
        
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < args.length; i++) {
            if (i > 0) sb.append(", ");
            sb.append(args[i] != null ? args[i].toString() : "null");
        }
        sb.append("]");
        return sb.toString();
    }
}

/**
 * 权限注解定义
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiredPermission {
    String value() default "";
    String role() default "";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Secured {
    String[] value();
}

/**
 * 安全上下文接口
 */
public interface SecurityContext {
    String getCurrentUsername();
    Set<String> getCurrentUserRoles();
    Set<String> getCurrentUserPermissions();
}

/**
 * 审计日志记录器
 */
public class AuditLogger {
    public static void log(String message) {
        System.out.println("[审计日志] " + new java.util.Date() + " - " + message);
    }
}
java 复制代码
/**
 * 受保护的业务服务
 */
@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
public interface EmployeeService {
    
    @RequiredPermission(permission = "employee:create", role = "ROLE_ADMIN")
    void createEmployee(Employee employee);
    
    @RequiredPermission(permission = "employee:read")
    Employee getEmployee(String id);
    
    @RequiredPermission(permission = "employee:update", role = "ROLE_MANAGER")
    void updateEmployee(Employee employee);
    
    @RequiredPermission(permission = "employee:delete", role = "ROLE_ADMIN")
    void deleteEmployee(String id);
}

/**
 * 客户端使用
 */
public class SecurityProxyDemo {
    
    public static void main(String[] args) {
        // 创建目标对象
        EmployeeService realService = new EmployeeServiceImpl();
        
        // 创建安全上下文(模拟)
        SecurityContext securityContext = createSecurityContext();
        
        // 创建安全代理
        EmployeeService proxy = (EmployeeService) java.lang.reflect.Proxy.newProxyInstance(
            EmployeeService.class.getClassLoader(),
            new Class[]{EmployeeService.class},
            new SecurityProxy(realService, securityContext)
        );
        
        // 测试权限控制
        System.out.println("=== 权限控制测试 ===");
        
        try {
            System.out.println("\n1. 测试创建员工(需要ROLE_ADMIN):");
            proxy.createEmployee(new Employee("001", "张三"));
        } catch (SecurityException e) {
            System.err.println("权限异常: " + e.getMessage());
        }
        
        try {
            System.out.println("\n2. 测试查询员工(需要employee:read权限):");
            Employee emp = proxy.getEmployee("001");
            System.out.println("查询成功: " + emp);
        } catch (SecurityException e) {
            System.err.println("权限异常: " + e.getMessage());
        }
    }
    
    private static SecurityContext createSecurityContext() {
        return new SecurityContext() {
            @Override
            public String getCurrentUsername() {
                return "user1";
            }
            
            @Override
            public Set<String> getCurrentUserRoles() {
                return java.util.Collections.singleton("ROLE_USER");
            }
            
            @Override
            public Set<String> getCurrentUserPermissions() {
                return java.util.Collections.singleton("employee:read");
            }
        };
    }
}

6.1.2 延迟加载代理(Lazy Loading)

场景描述:

在电商系统中,商品详情包含大量信息(基本信息、库存、评价、推荐等),但用户可能只查看基本信息。使用延迟加载代理可以在需要时才加载完整信息,提高系统响应速度。

实现方案:

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 延迟加载代理实现
 */
public class LazyLoadingProxy<T> implements InvocationHandler {
    
    private volatile T realObject;
    private final Callable<T> objectLoader;
    private final ExecutorService executorService;
    private Future<T> futureResult;
    
    public LazyLoadingProxy(Callable<T> objectLoader) {
        this.objectLoader = objectLoader;
        this.executorService = Executors.newSingleThreadExecutor();
    }
    
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(Class<T> interfaceClass, Callable<T> objectLoader) {
        return (T) Proxy.newProxyInstance(
            interfaceClass.getClassLoader(),
            new Class[]{interfaceClass},
            new LazyLoadingProxy<>(objectLoader)
        );
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 如果已经初始化,直接调用
        if (realObject != null) {
            return method.invoke(realObject, args);
        }
        
        // 检查方法是否需要触发加载
        if (shouldTriggerLoading(method)) {
            // 触发延迟加载
            triggerLazyLoading();
        }
        
        // 如果已经初始化,调用真实对象
        if (realObject != null) {
            return method.invoke(realObject, args);
        }
        
        // 返回默认值或占位符
        return getDefaultValue(method.getReturnType());
    }
    
    private synchronized void triggerLazyLoading() {
        // 双重检查锁定
        if (realObject != null) {
            return;
        }
        
        if (futureResult == null) {
            // 提交加载任务
            futureResult = executorService.submit(() -> {
                System.out.println("[延迟加载] 开始加载真实对象...");
                T obj = objectLoader.call();
                System.out.println("[延迟加载] 真实对象加载完成");
                return obj;
            });
        }
        
        try {
            // 等待加载完成
            realObject = futureResult.get();
            
            // 清理资源
            futureResult = null;
            executorService.shutdown();
            
        } catch (Exception e) {
            throw new RuntimeException("延迟加载失败", e);
        }
    }
    
    private boolean shouldTriggerLoading(Method method) {
        String methodName = method.getName();
        
        // 以下方法触发延迟加载
        return methodName.startsWith("get") || 
               methodName.startsWith("load") ||
               methodName.startsWith("fetch");
    }
    
    private Object getDefaultValue(Class<?> returnType) {
        if (returnType == boolean.class) return false;
        if (returnType == byte.class) return (byte) 0;
        if (returnType == short.class) return (short) 0;
        if (returnType == int.class) return 0;
        if (returnType == long.class) return 0L;
        if (returnType == float.class) return 0.0f;
        if (returnType == double.class) return 0.0;
        if (returnType == char.class) return '\0';
        if (returnType == Void.class || returnType == void.class) return null;
        
        // 引用类型返回null
        return null;
    }
}

/**
 * 商品详情服务接口
 */
public interface ProductDetailService {
    // 基本信息(不触发延迟加载)
    String getBasicInfo();
    
    // 库存信息(触发延迟加载)
    Inventory getInventory();
    
    // 评价信息(触发延迟加载)
    List<Review> getReviews();
    
    // 推荐商品(触发延迟加载)
    List<Product> getRecommendations();
}

/**
 * 使用示例
 */
public class LazyLoadingDemo {
    
    public static void main(String[] args) throws Exception {
        System.out.println("=== 延迟加载代理测试 ===");
        
        // 创建延迟加载代理
        ProductDetailService proxy = LazyLoadingProxy.createProxy(
            ProductDetailService.class,
            () -> {
                // 模拟耗时的对象创建过程
                Thread.sleep(2000);
                return new ProductDetailServiceImpl();
            }
        );
        
        System.out.println("\n1. 调用不触发加载的方法:");
        String basicInfo = proxy.getBasicInfo();
        System.out.println("基本信息: " + basicInfo);
        System.out.println("注意:真实对象尚未加载");
        
        System.out.println("\n2. 调用触发加载的方法:");
        System.out.println("开始获取库存信息...");
        long startTime = System.currentTimeMillis();
        
        Inventory inventory = proxy.getInventory();
        
        long endTime = System.currentTimeMillis();
        System.out.println("库存信息: " + inventory);
        System.out.println("加载耗时: " + (endTime - startTime) + "ms");
        
        System.out.println("\n3. 再次调用方法(已加载完成):");
        startTime = System.currentTimeMillis();
        List<Review> reviews = proxy.getReviews();
        endTime = System.currentTimeMillis();
        System.out.println("评价信息: " + reviews.size() + "条评价");
        System.out.println("调用耗时: " + (endTime - startTime) + "ms");
    }
}

6.1.3 远程代理(RPC框架)

场景描述:

在微服务架构中,服务之间需要远程调用。远程代理封装了网络通信细节,使客户端可以像调用本地方法一样调用远程服务。

实现方案:

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 简单的RPC远程代理实现
 */
public class RpcProxy implements InvocationHandler {
    
    private final String serviceUrl;
    private final Class<?> serviceInterface;
    private final Map<Method, String> methodCache = new ConcurrentHashMap<>();
    
    public RpcProxy(String serviceUrl, Class<?> serviceInterface) {
        this.serviceUrl = serviceUrl;
        this.serviceInterface = serviceInterface;
        initMethodCache();
    }
    
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(String serviceUrl, Class<T> serviceInterface) {
        return (T) Proxy.newProxyInstance(
            serviceInterface.getClassLoader(),
            new Class[]{serviceInterface},
            new RpcProxy(serviceUrl, serviceInterface)
        );
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 过滤Object类的方法
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(this, args);
        }
        
        // 构建RPC请求
        RpcRequest request = new RpcRequest();
        request.setServiceName(serviceInterface.getName());
        request.setMethodName(method.getName());
        request.setParameterTypes(method.getParameterTypes());
        request.setParameters(args);
        
        // 发送请求
        RpcResponse response = sendRequest(request);
        
        // 处理响应
        if (response.isError()) {
            throw response.getError();
        }
        
        return response.getResult();
    }
    
    private RpcResponse sendRequest(RpcRequest request) {
        try {
            // 序列化请求
            String requestBody = serialize(request);
            
            // 发送HTTP请求
            URL url = new URL(serviceUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setDoOutput(true);
            
            // 写入请求体
            try (java.io.OutputStream os = connection.getOutputStream()) {
                os.write(requestBody.getBytes());
                os.flush();
            }
            
            // 读取响应
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                String responseBody = readResponse(connection);
                return deserialize(responseBody, RpcResponse.class);
            } else {
                throw new RuntimeException("RPC调用失败,响应码: " + responseCode);
            }
            
        } catch (Exception e) {
            throw new RuntimeException("RPC调用异常", e);
        }
    }
    
    private void initMethodCache() {
        // 缓存方法信息,优化性能
        for (Method method : serviceInterface.getMethods()) {
            String key = method.getName() + "_" + 
                java.util.Arrays.toString(method.getParameterTypes());
            methodCache.put(method, key);
        }
    }
    
    private String serialize(Object obj) {
        // 使用JSON序列化
        return new com.fasterxml.jackson.databind.ObjectMapper()
            .writeValueAsString(obj);
    }
    
    private <T> T deserialize(String json, Class<T> type) {
        try {
            return new com.fasterxml.jackson.databind.ObjectMapper()
                .readValue(json, type);
        } catch (Exception e) {
            throw new RuntimeException("反序列化失败", e);
        }
    }
    
    private String readResponse(HttpURLConnection connection) throws Exception {
        try (java.io.BufferedReader reader = new java.io.BufferedReader(
            new java.io.InputStreamReader(connection.getInputStream()))) {
            
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return response.toString();
        }
    }
}

/**
 * RPC请求和响应对象
 */
class RpcRequest {
    private String serviceName;
    private String methodName;
    private Class<?>[] parameterTypes;
    private Object[] parameters;
    
    // getters and setters
}

class RpcResponse {
    private Object result;
    private Throwable error;
    private boolean isError;
    
    // getters and setters
}

/**
 * 远程服务接口
 */
public interface UserRemoteService {
    User getUserById(String id);
    List<User> searchUsers(String keyword);
    void updateUser(User user);
}

/**
 * 使用示例
 */
public class RpcProxyDemo {
    
    public static void main(String[] args) {
        System.out.println("=== RPC远程代理测试 ===");
        
        // 创建远程代理
        UserRemoteService proxy = RpcProxy.createProxy(
            "http://localhost:8080/api/user",
            UserRemoteService.class
        );
        
        // 像调用本地方法一样调用远程服务
        try {
            System.out.println("\n1. 查询用户信息:");
            User user = proxy.getUserById("123");
            System.out.println("查询结果: " + user);
            
            System.out.println("\n2. 搜索用户:");
            List<User> users = proxy.searchUsers("张");
            System.out.println("搜索结果: " + users.size() + "个用户");
            
        } catch (Exception e) {
            System.err.println("RPC调用异常: " + e.getMessage());
        }
    }
}

6.1.4 缓存代理

场景描述:

在内容管理系统中,热门文章的访问频率很高。使用缓存代理可以缓存查询结果,减少数据库压力,提高响应速度。

实现方案:

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 缓存代理实现
 */
public class CacheProxy implements InvocationHandler {
    
    private final Object target;
    private final CacheManager cacheManager;
    private final Map<Method, CacheConfig> cacheConfigs = new ConcurrentHashMap<>();
    
    public CacheProxy(Object target, CacheManager cacheManager) {
        this.target = target;
        this.cacheManager = cacheManager;
        initCacheConfigs();
    }
    
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target, CacheManager cacheManager) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new CacheProxy(target, cacheManager)
        );
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 获取缓存配置
        CacheConfig config = cacheConfigs.get(method);
        
        // 如果没有缓存配置,直接调用
        if (config == null) {
            return method.invoke(target, args);
        }
        
        // 生成缓存key
        String cacheKey = generateCacheKey(method, args, config);
        
        // 尝试从缓存获取
        Object cachedValue = cacheManager.get(cacheKey);
        if (cachedValue != null) {
            System.out.println("[缓存命中] key: " + cacheKey);
            return cachedValue;
        }
        
        System.out.println("[缓存未命中] key: " + cacheKey + ", 执行目标方法");
        
        // 执行目标方法
        Object result = method.invoke(target, args);
        
        // 缓存结果
        if (result != null && config.isCacheable(result)) {
            cacheManager.put(cacheKey, result, config.getTtl(), config.getTimeUnit());
            System.out.println("[缓存写入] key: " + cacheKey + ", ttl: " + config.getTtl() + config.getTimeUnit());
        }
        
        return result;
    }
    
    private void initCacheConfigs() {
        // 解析方法上的缓存注解
        for (Method method : target.getClass().getMethods()) {
            Cacheable cacheable = method.getAnnotation(Cacheable.class);
            if (cacheable != null) {
                cacheConfigs.put(method, new CacheConfig(cacheable));
            }
        }
    }
    
    private String generateCacheKey(Method method, Object[] args, CacheConfig config) {
        StringBuilder keyBuilder = new StringBuilder();
        
        // 使用配置的缓存名称
        keyBuilder.append(config.getCacheName());
        keyBuilder.append(":");
        
        // 添加类名和方法名
        keyBuilder.append(target.getClass().getSimpleName());
        keyBuilder.append(".");
        keyBuilder.append(method.getName());
        
        // 添加参数哈希
        if (args != null && args.length > 0) {
            keyBuilder.append(":");
            for (Object arg : args) {
                keyBuilder.append(arg != null ? arg.hashCode() : "null");
                keyBuilder.append("_");
            }
        }
        
        return keyBuilder.toString();
    }
}

/**
 * 缓存管理器接口
 */
interface CacheManager {
    Object get(String key);
    void put(String key, Object value, long ttl, TimeUnit timeUnit);
    void remove(String key);
    void clear();
}

/**
 * 基于内存的缓存管理器实现
 */
class MemoryCacheManager implements CacheManager {
    
    private static class CacheEntry {
        final Object value;
        final long expireTime;
        
        CacheEntry(Object value, long expireTime) {
            this.value = value;
            this.expireTime = expireTime;
        }
        
        boolean isExpired() {
            return System.currentTimeMillis() > expireTime;
        }
    }
    
    private final Map<String, CacheEntry> cache = new ConcurrentHashMap<>();
    private final ScheduledExecutorService cleanupExecutor = 
        Executors.newSingleThreadScheduledExecutor();
    
    public MemoryCacheManager() {
        // 定期清理过期缓存
        cleanupExecutor.scheduleAtFixedRate(this::cleanupExpired, 1, 1, TimeUnit.MINUTES);
    }
    
    @Override
    public Object get(String key) {
        CacheEntry entry = cache.get(key);
        if (entry == null) {
            return null;
        }
        
        if (entry.isExpired()) {
            cache.remove(key);
            return null;
        }
        
        return entry.value;
    }
    
    @Override
    public void put(String key, Object value, long ttl, TimeUnit timeUnit) {
        long expireTime = System.currentTimeMillis() + timeUnit.toMillis(ttl);
        cache.put(key, new CacheEntry(value, expireTime));
    }
    
    @Override
    public void remove(String key) {
        cache.remove(key);
    }
    
    @Override
    public void clear() {
        cache.clear();
    }
    
    private void cleanupExpired() {
        cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
    }
}

/**
 * 缓存配置类
 */
class CacheConfig {
    private final String cacheName;
    private final long ttl;
    private final TimeUnit timeUnit;
    
    CacheConfig(Cacheable annotation) {
        this.cacheName = annotation.value();
        this.ttl = annotation.ttl();
        this.timeUnit = annotation.unit();
    }
    
    boolean isCacheable(Object result) {
        // 可以根据结果类型决定是否缓存
        return result != null;
    }
    
    // getters
}

/**
 * 缓存注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Cacheable {
    String value() default "default";
    long ttl() default 300;
    TimeUnit unit() default TimeUnit.SECONDS;
}

/**
 * 文章服务接口
 */
public interface ArticleService {
    @Cacheable(value = "article", ttl = 600)
    Article getArticleById(String id);
    
    @Cacheable(value = "hotArticles", ttl = 300)
    List<Article> getHotArticles(int limit);
    
    void updateArticle(Article article);
}

/**
 * 使用示例
 */
public class CacheProxyDemo {
    
    public static void main(String[] args) throws Exception {
        System.out.println("=== 缓存代理测试 ===");
        
        // 创建缓存管理器
        CacheManager cacheManager = new MemoryCacheManager();
        
        // 创建目标对象
        ArticleService realService = new ArticleServiceImpl();
        
        // 创建缓存代理
        ArticleService proxy = CacheProxy.createProxy(realService, cacheManager);
        
        // 测试缓存效果
        System.out.println("\n1. 第一次查询文章(缓存未命中):");
        long startTime = System.currentTimeMillis();
        Article article1 = proxy.getArticleById("123");
        long endTime = System.currentTimeMillis();
        System.out.println("查询结果: " + article1.getTitle());
        System.out.println("查询耗时: " + (endTime - startTime) + "ms");
        
        System.out.println("\n2. 第二次查询同一文章(缓存命中):");
        startTime = System.currentTimeMillis();
        Article article2 = proxy.getArticleById("123");
        endTime = System.currentTimeMillis();
        System.out.println("查询结果: " + article2.getTitle());
        System.out.println("查询耗时: " + (endTime - startTime) + "ms");
        
        System.out.println("\n3. 更新文章后查询(缓存失效):");
        article1.setTitle("更新后的标题");
        proxy.updateArticle(article1);
        
        startTime = System.currentTimeMillis();
        Article article3 = proxy.getArticleById("123");
        endTime = System.currentTimeMillis();
        System.out.println("查询结果: " + article3.getTitle());
        System.out.println("查询耗时: " + (endTime - startTime) + "ms");
        
        System.out.println("\n4. 查询热门文章列表:");
        List<Article> hotArticles = proxy.getHotArticles(10);
        System.out.println("热门文章数量: " + hotArticles.size());
    }
}

6.1.5 智能引用代理

场景描述:

在大对象管理场景中,需要监控对象的访问情况,实现自动清理不常用的对象,优化内存使用。

实现方案:

java 复制代码
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 智能引用代理实现
 * 监控对象访问,自动管理对象生命周期
 */
public class SmartReferenceProxy implements InvocationHandler {
    
    private final Object target;
    private final ReferenceType referenceType;
    private final AtomicInteger accessCount = new AtomicInteger(0);
    private final long createdTime = System.currentTimeMillis();
    private volatile long lastAccessTime = createdTime;
    
    private static final Map<Object, SmartReferenceProxy> proxyRegistry = 
        new ConcurrentHashMap<>();
    private static final ReferenceQueue<Object> referenceQueue = 
        new ReferenceQueue<>();
    
    public enum ReferenceType {
        STRONG,    // 强引用
        SOFT,      // 软引用(内存不足时回收)
        WEAK       // 弱引用(GC时回收)
    }
    
    private SmartReferenceProxy(Object target, ReferenceType referenceType) {
        this.target = target;
        this.referenceType = referenceType;
    }
    
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T target, ReferenceType referenceType) {
        SmartReferenceProxy handler = new SmartReferenceProxy(target, referenceType);
        
        T proxy = (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            handler
        );
        
        // 注册代理
        proxyRegistry.put(proxy, handler);
        
        // 根据引用类型创建不同的引用
        switch (referenceType) {
            case SOFT:
                new SoftReference<>(proxy, referenceQueue);
                break;
            case WEAK:
                new WeakReference<>(proxy, referenceQueue);
                break;
            case STRONG:
            default:
                // 强引用不需要特殊处理
                break;
        }
        
        return proxy;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 更新访问统计
        accessCount.incrementAndGet();
        lastAccessTime = System.currentTimeMillis();
        
        // 记录访问日志
        logAccess(method);
        
        // 执行目标方法
        return method.invoke(target, args);
    }
    
    private void logAccess(Method method) {
        System.out.printf("[智能引用] 对象访问 - 方法: %s, 总访问次数: %d, 最后访问: %tT%n",
            method.getName(),
            accessCount.get(),
            new java.util.Date(lastAccessTime)
        );
    }
    
    /**
     * 获取对象访问统计
     */
    public AccessStatistics getStatistics() {
        long currentTime = System.currentTimeMillis();
        long idleTime = currentTime - lastAccessTime;
        
        return new AccessStatistics(
            accessCount.get(),
            createdTime,
            lastAccessTime,
            idleTime
        );
    }
    
    /**
     * 访问统计信息
     */
    public static class AccessStatistics {
        private final int totalAccessCount;
        private final long createdTime;
        private final long lastAccessTime;
        private final long idleTime;
        
        public AccessStatistics(int totalAccessCount, long createdTime, 
                               long lastAccessTime, long idleTime) {
            this.totalAccessCount = totalAccessCount;
            this.createdTime = createdTime;
            this.lastAccessTime = lastAccessTime;
            this.idleTime = idleTime;
        }
        
        // getters
    }
    
    /**
     * 监控线程,定期清理和报告
     */
    static class ReferenceMonitor extends Thread {
        private volatile boolean running = true;
        
        @Override
        public void run() {
            while (running) {
                try {
                    // 检查引用队列
                    checkReferenceQueue();
                    
                    // 报告统计信息
                    reportStatistics();
                    
                    // 休眠一段时间
                    Thread.sleep(5000);
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
        
        private void checkReferenceQueue() {
            java.lang.ref.Reference<?> ref;
            while ((ref = referenceQueue.poll()) != null) {
                System.out.println("[监控] 对象已被回收: " + ref);
            }
        }
        
        private void reportStatistics() {
            if (proxyRegistry.isEmpty()) {
                return;
            }
            
            System.out.println("\n=== 对象访问统计报告 ===");
            System.out.println("活动对象数量: " + proxyRegistry.size());
            
            proxyRegistry.forEach((proxy, handler) -> {
                AccessStatistics stats = handler.getStatistics();
                System.out.printf("对象: %s, 访问次数: %d, 空闲时间: %dms%n",
                    proxy.getClass().getSimpleName(),
                    stats.totalAccessCount,
                    stats.idleTime
                );
            });
        }
        
        public void shutdown() {
            running = false;
            interrupt();
        }
    }
}

/**
 * 大对象接口
 */
public interface LargeObject {
    byte[] getData();
    void process();
    String getId();
}

/**
 * 使用示例
 */
public class SmartReferenceDemo {
    
    public static void main(String[] args) throws Exception {
        System.out.println("=== 智能引用代理测试 ===");
        
        // 启动监控线程
        SmartReferenceProxy.ReferenceMonitor monitor = 
            new SmartReferenceProxy.ReferenceMonitor();
        monitor.setDaemon(true);
        monitor.start();
        
        // 创建不同引用类型的代理
        System.out.println("\n1. 创建软引用代理:");
        LargeObject softProxy = SmartReferenceProxy.createProxy(
            createLargeObject("soft-obj"),
            SmartReferenceProxy.ReferenceType.SOFT
        );
        
        System.out.println("\n2. 创建弱引用代理:");
        LargeObject weakProxy = SmartReferenceProxy.createProxy(
            createLargeObject("weak-obj"),
            SmartReferenceProxy.ReferenceType.WEAK
        );
        
        System.out.println("\n3. 创建强引用代理:");
        LargeObject strongProxy = SmartReferenceProxy.createProxy(
            createLargeObject("strong-obj"),
            SmartReferenceProxy.ReferenceType.STRONG
        );
        
        // 模拟访问
        System.out.println("\n4. 模拟对象访问:");
        for (int i = 0; i < 3; i++) {
            System.out.println("\n第 " + (i + 1) + " 轮访问:");
            
            softProxy.getData();
            weakProxy.process();
            strongProxy.getId();
            
            // 间隔一段时间
            Thread.sleep(1000);
        }
        
        // 获取统计信息
        System.out.println("\n5. 查看统计信息:");
        printStatistics(softProxy, "软引用对象");
        printStatistics(weakProxy, "弱引用对象");
        printStatistics(strongProxy, "强引用对象");
        
        // 模拟内存压力,触发GC
        System.out.println("\n6. 模拟内存压力:");
        simulateMemoryPressure();
        
        // 等待监控线程报告
        Thread.sleep(10000);
        
        // 停止监控
        monitor.shutdown();
    }
    
    private static LargeObject createLargeObject(String id) {
        return new LargeObject() {
            private final byte[] data = new byte[1024 * 1024]; // 1MB数据
            
            @Override
            public byte[] getData() {
                System.out.println("获取对象数据: " + id);
                return data;
            }
            
            @Override
            public void process() {
                System.out.println("处理对象: " + id);
            }
            
            @Override
            public String getId() {
                return id;
            }
        };
    }
    
    private static void printStatistics(Object proxy, String label) {
        SmartReferenceProxy handler = SmartReferenceProxy.proxyRegistry.get(proxy);
        if (handler != null) {
            SmartReferenceProxy.AccessStatistics stats = handler.getStatistics();
            System.out.printf("%s - 访问次数: %d, 空闲时间: %dms%n",
                label, stats.totalAccessCount, stats.idleTime);
        }
    }
    
    private static void simulateMemoryPressure() {
        System.out.println("创建大量对象模拟内存压力...");
        List<byte[]> memoryHog = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            memoryHog.add(new byte[1024 * 1024]); // 每次分配1MB
        }
        
        // 触发GC
        System.gc();
        
        // 清理引用,让GC可以回收
        memoryHog.clear();
    }
}

6.2 企业级应用案例

框架/技术 代理应用 实现方式
Spring Framework AOP切面编程 JDK/CGLIB代理
MyBatis Mapper接口实现 JDK动态代理
Hibernate 延迟加载 CGLIB代理
Spring Security 方法安全控制 AOP代理
Dubbo 远程服务调用 动态代理
Java RMI 远程对象访问 动态代理
Mockito 测试模拟对象 动态代理

7. 代理模式的最佳实践

7.1 设计原则

  1. 单一职责原则 :代理类专注访问控制,真实类专注业务逻辑

    java 复制代码
    // 真实类 - 业务逻辑
    class PaymentProcessor {
        public void processPayment(double amount) {
            // 核心支付逻辑
        }
    }
    
    // 代理类 - 附加功能
    class PaymentProxy {
        private PaymentProcessor processor;
        
        public void processPayment(double amount) {
            validate(amount);  // 验证
            log(amount);       // 日志
            processor.processPayment(amount); // 委托
            notify();          // 通知
        }
    }
  2. 开闭原则:通过代理扩展功能,无需修改真实类

  3. 迪米特法则:客户端仅与代理交互,不与真实类直接耦合

7.2 性能优化策略

  1. 代理对象缓存:复用已创建的代理实例,特别是在高并发场景下。
java 复制代码
public class ProxyCacheManager {
    
    private static final ConcurrentHashMap<CacheKey, Object> PROXY_CACHE = 
        new ConcurrentHashMap<>();
    
    private static class CacheKey {
        final Class<?> targetClass;
        final Class<?>[] interfaces;
        
        CacheKey(Class<?> targetClass, Class<?>[] interfaces) {
            this.targetClass = targetClass;
            this.interfaces = interfaces;
        }
        
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            CacheKey cacheKey = (CacheKey) o;
            return targetClass.equals(cacheKey.targetClass) &&
                   Arrays.equals(interfaces, cacheKey.interfaces);
        }
        
        @Override
        public int hashCode() {
            int result = targetClass.hashCode();
            result = 31 * result + Arrays.hashCode(interfaces);
            return result;
        }
    }
    
    @SuppressWarnings("unchecked")
    public static <T> T getCachedProxy(T target, Class<T> interfaceType) {
        CacheKey key = new CacheKey(
            target.getClass(),
            new Class<?>[]{interfaceType}
        );
        
        return (T) PROXY_CACHE.computeIfAbsent(key, k -> 
            createProxy(target, interfaceType)
        );
    }
    
    private static <T> T createProxy(T target, Class<T> interfaceType) {
        return (T) Proxy.newProxyInstance(
            interfaceType.getClassLoader(),
            new Class<?>[]{interfaceType},
            new CachingInvocationHandler(target)
        );
    }
}
  1. 延迟初始化 :真实对象按需创建

    java 复制代码
    public class LazyInitProxy implements InvocationHandler {
        private volatile Object target;
        private final Supplier<?> creator;
        
        public Object invoke(Object proxy, Method method, Object[] args) {
            if (target == null) {
                synchronized (this) { // 双重检查锁定
                    if (target == null) {
                        target = creator.get();
                    }
                }
            }
            return method.invoke(target, args);
        }
    }
  2. 方法缓存优化:缓存Method对象,避免重复反射获取。

java 复制代码
public class OptimizedMethodInterceptor implements MethodInterceptor {
    
    private final Map<Method, FastMethod> methodCache = new ConcurrentHashMap<>();
    
    @Override
    public Object intercept(Object obj, Method method, Object[] args, 
                           MethodProxy proxy) throws Throwable {
        
        FastMethod fastMethod = methodCache.computeIfAbsent(method, m -> 
            createFastMethod(m, proxy)
        );
        
        return fastMethod.invoke(obj, args);
    }
    
    private FastMethod createFastMethod(Method method, MethodProxy proxy) {
        // 使用字节码生成优化方法调用
        return new FastMethod() {
            @Override
            public Object invoke(Object obj, Object[] args) throws Throwable {
                return proxy.invokeSuper(obj, args);
            }
        };
    }
    
    interface FastMethod {
        Object invoke(Object obj, Object[] args) throws Throwable;
    }
}

7.3 安全实践

  1. 封装真实对象:避免直接暴露

    java 复制代码
    // 正确做法:私有封装
    public class SafeProxy {
        private final Object target;
    }
  2. 防御性编程:验证代理参数

    java 复制代码
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 参数验证
        if (args == null || args.length == 0) {
            throw new IllegalArgumentException("参数错误");
        }
        // ... 
    }
  3. 权限最小化:代理仅暴露必要方法

  4. 异常处理:合理处理代理中的异常

    java 复制代码
    try {
        return method.invoke(target, args);
    } catch (InvocationTargetException e) {
        throw e.getTargetException(); // 抛出真实异常
    }

8.代理模式与其他模式对比

8.1 代理 vs 装饰器模式

维度 代理模式 装饰器模式
目的 控制访问 增强功能
关系 代理知道真实对象 装饰器与被装饰对象实现相同接口
创建 代理可控制创建 装饰器接收已有对象
关注点 访问机制 功能扩展

8.2 代理 vs 适配器模式

维度 代理模式 适配器模式
目的 控制访问 接口转换
关系 相同接口 不同接口间转换

9.总结与进阶思考

9.1 核心总结

  • 静态代理:简单直观,适合接口稳定、代理类少的场景
  • JDK动态代理:接口代理标准方案,依赖Java反射
  • CGLIB代理:无接口代理首选,字节码增强技术
  • Spring AOP:企业级代理最佳实践,自动选择代理方式

9.2 进阶思考

  1. . 性能深度优化

    • 使用Byte Buddy或Javassist替代CGLIB
    • 预生成代理类减少运行时开销
    • GraalVM原生镜像优化代理模式
  2. 云原生时代

    • 服务网格(Service Mesh)中的边车代理
    • Kubernetes API服务器中的准入控制器
    • 微服务网关的代理模式应用
  3. 架构演进

    静态代理 JDK动态代理 CGLIB字节码增强 Spring AOP 云原生服务网格

代理模式演进趋势

  • 框架集成:现代框架(如Spring、Quarkus)内置代理优化
  • 编译时织入:减少运行时开销(如Micronaut AOT)
  • 云原生支持:服务网格中的代理模式新形态
  • 多语言应用:跨语言代理解决方案(如gRPC代理)

架构师箴言 :"代理模式是系统边界的守护者,它在安全与效率之间找到平衡点。优秀的架构师懂得在何处设置代理,正如将军懂得在何处设置哨卡。"
------ Martin Fowler,《企业应用架构模式》

相关推荐
wepe122 小时前
FlyEnv---phpstudy平替
java·python·mysql·nginx·php
Echo flower2 小时前
使用Java将HTML内容转换为Word文档
java·html·word
一人の梅雨2 小时前
京东商品详情接口深度解析:从宙斯签名到商详数据价值重构
java·spring cloud·微服务
spencer_tseng2 小时前
org.eclipse.wst.common.project.facet.core.xml could not be read.
xml·java·eclipse
Lisonseekpan2 小时前
为什么Spring 推荐使用构造器注入而非@Autowired字段注入?
java·后端·spring·log4j
Lovely Ruby2 小时前
Cursor 迁移到 Zed 编辑器
java·缓存·编辑器
Gu_yyqx2 小时前
IDEA中debug的使用
java·ide·intellij-idea
老华带你飞2 小时前
个人网盘管理|基于springboot + vue个人网盘管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端