一、代理模式核心概念1. 定义代理模式是一种结构型设计模式核心思想是通过一个 代理类 为目标类提供间接访问在不修改目标类代码的前提下对目标类的功能进行增强如日志记录、权限校验、性能监控等。2. 核心角色表格角色职责抽象主题Subject定义目标类和代理类的公共接口确保代理类与目标类行为一致目标对象RealSubject真正执行业务逻辑的类是代理的目标代理对象Proxy实现抽象主题接口持有目标对象引用在调用目标方法前后添加增强逻辑3. 代理模式的价值解耦业务逻辑与非业务逻辑如日志、事务分离增强无侵入式扩展目标类功能控制可控制对目标对象的访问如权限校验是 AOP面向切面编程的底层实现核心。二、静态代理1. 实现步骤步骤 1定义抽象主题接口// 抽象主题订单服务接口 public interface OrderService { // 创建订单 void createOrder(String orderNo); // 取消订单 void cancelOrder(String orderNo); }步骤 2实现目标类真实主题// 目标对象订单服务实现类 public class OrderServiceImpl implements OrderService { Override public void createOrder(String orderNo) { System.out.println(【目标类】创建订单 orderNo); } Override public void cancelOrder(String orderNo) { System.out.println(【目标类】取消订单 orderNo); } }步骤 3实现静态代理类// 静态代理类增强订单服务的功能 public class OrderServiceStaticProxy implements OrderService { // 持有目标对象引用 private final OrderService target; // 通过构造器注入目标对象 public OrderServiceStaticProxy(OrderService target) { this.target target; } Override public void createOrder(String orderNo) { // 前置增强日志记录 权限校验 before(createOrder, orderNo); // 调用目标方法 target.createOrder(orderNo); // 后置增强记录耗时 after(createOrder); } Override public void cancelOrder(String orderNo) { before(cancelOrder, orderNo); target.cancelOrder(orderNo); after(cancelOrder); } // 前置增强逻辑 private void before(String methodName, String orderNo) { System.out.println(【静态代理】前置增强调用 methodName 方法参数 orderNo); System.out.println(【静态代理】权限校验通过); } // 后置增强逻辑 private void after(String methodName) { System.out.println(【静态代理】后置增强 methodName 方法执行完成); } }步骤 4测试静态代理public class StaticProxyTest { public static void main(String[] args) { // 1. 创建目标对象 OrderService target new OrderServiceImpl(); // 2. 创建代理对象 OrderService proxy new OrderServiceStaticProxy(target); // 3. 通过代理对象调用方法 proxy.createOrder(ORDER_001); System.out.println(------------------------); proxy.cancelOrder(ORDER_001); } }输出结果【静态代理】前置增强调用createOrder方法参数ORDER_001 【静态代理】权限校验通过 【目标类】创建订单ORDER_001 【静态代理】后置增强createOrder方法执行完成 ------------------------ 【静态代理】前置增强调用cancelOrder方法参数ORDER_001 【静态代理】权限校验通过 【目标类】取消订单ORDER_001 【静态代理】后置增强cancelOrder方法执行完成2. 静态代理的优缺点优点缺点实现简单易于理解和调试代理类与目标类一一对应类数量爆炸维护成本高无侵入式增强目标类功能接口变更时代理类和目标类需同步修改逻辑清晰增强代码集中无法动态扩展新增目标类需手动编写代理类三、JDK 动态代理1. 核心原理JDK 动态代理是 JDK 原生支持的代理方式基于接口实现无需手动编写代理类运行时通过java.lang.reflect.Proxy动态生成代理类字节码核心依赖InvocationHandler接口统一处理代理对象的方法调用要求目标类必须实现至少一个接口否则无法使用。2. 核心类 / 接口类 / 接口核心作用Proxy生成动态代理类的核心类核心方法newProxyInstance()InvocationHandler代理逻辑处理器通过invoke()方法统一处理所有代理方法的增强逻辑3. 实现步骤步骤 1复用抽象主题和目标类同静态代理的 OrderService/OrderServiceImpl步骤 2实现 InvocationHandler 接口import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; // JDK动态代理处理器统一处理所有代理方法的增强逻辑 public class JdkDynamicProxyHandler implements InvocationHandler { // 目标对象通用类型适配所有接口 private final Object target; public JdkDynamicProxyHandler(Object target) { this.target target; } /** * 代理方法的核心处理逻辑 * param proxy 生成的代理对象一般不用 * param method 被调用的目标方法 * param args 方法入参 * return 目标方法的返回值 * throws Throwable 方法执行异常 */ Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 前置增强 before(method.getName(), args); // 执行目标方法 Object result method.invoke(target, args); // 后置增强 after(method.getName()); return result; } // 通用前置增强逻辑 private void before(String methodName, Object[] args) { System.out.println(【JDK动态代理】前置增强调用 methodName 方法参数 (args ! null ? args[0] : 无)); System.out.println(【JDK动态代理】权限校验通过); } // 通用后置增强逻辑 private void after(String methodName) { System.out.println(【JDK动态代理】后置增强 methodName 方法执行完成); } }步骤 3生成动态代理对象并测试import java.lang.reflect.Proxy; public class JdkDynamicProxyTest { public static void main(String[] args) { // 1. 创建目标对象 OrderService target new OrderServiceImpl(); // 2. 创建代理处理器 InvocationHandler handler new JdkDynamicProxyHandler(target); // 3. 生成动态代理对象核心方法 OrderService proxy (OrderService) Proxy.newProxyInstance( target.getClass().getClassLoader(), // 目标类类加载器 target.getClass().getInterfaces(), // 目标类实现的接口 handler // 代理处理器 ); // 4. 通过代理对象调用方法 proxy.createOrder(ORDER_002); System.out.println(------------------------); proxy.cancelOrder(ORDER_002); // 打印代理类的类名验证动态生成 System.out.println(------------------------); System.out.println(代理类的类名 proxy.getClass().getName()); } }输出结果【JDK动态代理】前置增强调用createOrder方法参数ORDER_002 【JDK动态代理】权限校验通过 【目标类】创建订单ORDER_002 【JDK动态代理】后置增强createOrder方法执行完成 ------------------------ 【JDK动态代理】前置增强调用cancelOrder方法参数ORDER_002 【JDK动态代理】权限校验通过 【目标类】取消订单ORDER_002 【JDK动态代理】后置增强cancelOrder方法执行完成 ------------------------ 代理类的类名com.sun.proxy.$Proxy04. JDK 动态代理的优缺点优点缺点无需手动编写代理类灵活扩展目标类必须实现接口局限性代理逻辑统一维护成本低仅能代理接口中定义的方法无法代理类方法JDK 原生支持无需额外依赖底层基于反射性能略低于 CGLIB四、CGLIB 动态代理1. 核心原理CGLIBCode Generation Library是第三方字节码生成库基于继承实现无需目标类实现接口通过继承目标类动态生成子类作为代理类底层通过 ASM 框架操作字节码直接生成新的类文件Spring、MyBatis 等框架均内置 CGLIB 依赖。2. 前置条件引入 CGLIB 依赖Spring 项目无需手动引入单独使用需添加!-- Maven 依赖 -- dependency groupIdcglib/groupId artifactIdcglib/artifactId version3.3.0/version /dependency3. 核心类 / 接口类 / 接口核心作用EnhancerCGLIB 核心类用于生成代理类类似 JDK 的ProxyMethodInterceptor方法拦截器替代 JDK 的InvocationHandler通过intercept()处理增强MethodProxy目标方法的代理对象可优化方法调用性能避免反射4. 实现步骤步骤 1创建无接口的目标类CGLIB 适配无接口场景// 无接口的目标类用户服务 public class UserService { public void addUser(String username) { System.out.println(【目标类】添加用户 username); } public void deleteUser(String username) { System.out.println(【目标类】删除用户 username); } // 注意final方法无法被CGLIB代理子类无法重写 public final void queryUser(String username) { System.out.println(【目标类】查询用户 username); } }步骤 2实现 MethodInterceptor 接口import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; // CGLIB方法拦截器处理代理增强逻辑 public class CglibMethodInterceptor implements MethodInterceptor { // 目标对象 private final Object target; public CglibMethodInterceptor(Object target) { this.target target; } /** * 拦截目标方法调用 * param proxy 代理对象子类实例 * param method 目标方法 * param args 方法入参 * param methodProxy 方法代理对象优化调用 * return 目标方法返回值 * throws Throwable 执行异常 */ Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { // 前置增强 before(method.getName(), args); // 执行目标方法两种方式反射 / methodProxy.invokeSuper Object result methodProxy.invokeSuper(proxy, args); // 推荐性能更高 // Object result method.invoke(target, args); // 反射方式 // 后置增强 after(method.getName()); return result; } private void before(String methodName, Object[] args) { System.out.println(【CGLIB代理】前置增强调用 methodName 方法参数 (args ! null ? args[0] : 无)); System.out.println(【CGLIB代理】参数校验通过); } private void after(String methodName) { System.out.println(【CGLIB代理】后置增强 methodName 方法执行完成); } }步骤 3生成 CGLIB 代理对象并测试import net.sf.cglib.proxy.Enhancer; public class CglibProxyTest { public static void main(String[] args) { // 1. 创建目标对象 UserService target new UserService(); // 2. 创建CGLIB增强器 Enhancer enhancer new Enhancer(); // 设置父类目标类 enhancer.setSuperclass(UserService.class); // 设置方法拦截器 enhancer.setCallback(new CglibMethodInterceptor(target)); // 3. 生成代理对象子类实例 UserService proxy (UserService) enhancer.create(); // 4. 调用代理方法 proxy.addUser(张三); System.out.println(------------------------); proxy.deleteUser(张三); System.out.println(------------------------); proxy.queryUser(张三); // final方法无增强逻辑直接执行目标方法 // 打印代理类的类名 System.out.println(------------------------); System.out.println(代理类的类名 proxy.getClass().getName()); } }输出结果【CGLIB代理】前置增强调用addUser方法参数张三 【CGLIB代理】参数校验通过 【目标类】添加用户张三 【CGLIB代理】后置增强addUser方法执行完成 ------------------------ 【CGLIB代理】前置增强调用deleteUser方法参数张三 【CGLIB代理】参数校验通过 【目标类】删除用户张三 【CGLIB代理】后置增强deleteUser方法执行完成 ------------------------ 【目标类】查询用户张三 ------------------------ 代理类的类名com.example.proxy.UserService$$EnhancerByCGLIB$$xxxxxxx5. CGLIB 代理的注意事项final 方法无法被代理CGLIB 基于继承子类无法重写 final 方法目标类不能是 final 类final 类无法被继承无法生成代理子类性能优于 JDK 动态代理ASM 直接操作字节码避免反射开销构造方法会被调用两次生成代理类时会先创建目标类实例需注意无参构造的影响。6. CGLIB 与 JDK 动态代理对比特性JDK 动态代理CGLIB 动态代理实现方式基于接口实现接口基于继承继承目标类目标类要求必须实现接口无需实现接口不能是 final核心类Proxy、InvocationHandlerEnhancer、MethodInterceptor性能反射调用性能略低字节码生成性能更高适用场景目标类有接口目标类无接口五、代理模式与 AOP 的关系1. AOP 核心概念AOP面向切面编程是一种编程思想核心是将非业务逻辑如日志、事务、权限从业务逻辑中抽离形成 切面并动态织入到业务方法中。2. AOP 与代理模式的映射AOP 概念代理模式对应角色切面Aspect代理类中的增强逻辑before/after连接点JoinPoint目标类的所有方法切入点Pointcut被增强的具体方法通知Advice前置 / 后置 / 环绕等增强逻辑目标对象Target代理模式中的目标对象代理对象Proxy代理模式中的代理对象3. Spring AOP 的代理选择策略Spring AOP 底层默认使用动态代理选择规则如果目标类实现了接口优先使用 JDK 动态代理如果目标类未实现接口使用 CGLIB 动态代理可通过配置spring.aop.proxy-target-classtrue强制使用 CGLIB。六、实战案例基于代理实现统一日志切面import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.time.LocalDateTime; // 通用日志代理处理器 public class LogProxyHandler implements InvocationHandler { private final Object target; public LogProxyHandler(Object target) { this.target target; } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 1. 前置日志记录方法调用信息 String log String.format( [%s] 调用方法%s.%s参数%s调用者%s, LocalDateTime.now(), target.getClass().getName(), method.getName(), args null ? 无 : String.join(,, args.toString()), Thread.currentThread().getName() ); System.out.println(【日志切面】 log); // 2. 执行目标方法处理异常 Object result null; try { result method.invoke(target, args); // 3. 后置日志记录方法成功执行 System.out.println(【日志切面】方法执行成功返回值 result); } catch (Exception e) { // 4. 异常日志记录方法执行异常 System.out.println(【日志切面】方法执行异常 e.getMessage()); throw e; // 抛出异常不影响业务逻辑 } finally { // 5. 最终日志记录方法执行完成 System.out.println(【日志切面】方法执行完成); } return result; } // 通用代理生成方法 public static T T createProxy(T target) { return (T) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new LogProxyHandler(target) ); } } // 测试为任意业务类添加日志增强 public class LogProxyTest { public static void main(String[] args) { // 1. 业务类实现接口 OrderService orderService LogProxyHandler.createProxy(new OrderServiceImpl()); orderService.createOrder(ORDER_003); // 2. 若业务类无接口可替换为CGLIB实现 // UserService userService CglibLogProxy.createProxy(new UserService()); // userService.addUser(李四); } }总结代理模式分为静态代理和动态代理静态代理手动编写代理类适用于简单场景动态代理JDK/CGLIB运行时生成代理类是 AOP 核心JDK 与 CGLIB 代理的核心区别JDK 基于接口CGLIB 基于继承Spring AOP 会自动选择适配方式代理模式是 AOP 的底层实现通过代理类将切面逻辑日志、事务等织入目标方法实现业务与非业务逻辑的解耦。