【从0开始学习Java | 第23篇】动态代理

【从0开始学习Java | 第23篇】动态代理
在这里插入图片描述

文章目录

Java动态代理概述

在Java开发中,代理模式设计模式之一,而动态代理作为代理模式的进阶形式,在框架开发(如Spring AOP)、日志记录、权限控制等场景中发挥着关键作用。本文将从核心概念出发,拆解两种主流动态代理的实现逻辑,并分析其适用场景。

在这里插入图片描述

一、动态代理的核心概念

动态代理指在程序运行时,通过反射机制动态生成代理类,而非在编译期预先定义。其核心价值在于:无需为每个目标类手动编写代理类,即可统一为多个目标类添加横切逻辑(如日志、事务、异常处理),降低代码耦合度。

在这里插入图片描述

动态代理包含三个核心角色:

  1. 目标类(Target):被代理的原始类,包含核心业务逻辑;
  2. 代理类(Proxy):运行时动态生成的类,持有目标类引用,负责调用目标方法并增强逻辑;
  3. 增强逻辑(Advice):需统一添加的横切逻辑,如日志打印、参数校验等。

形象解释

在这里插入图片描述

二、两种主流动态代理实现

Java中动态代理主要有两种实现方式:JDK动态代理(原生API)和CGLIB动态代理(第三方库),二者在原理和使用上存在显著差异。

1. JDK动态代理(基于接口)

原理

JDK动态代理依赖java.lang.reflect包下的ProxyInvocationHandler接口,要求目标类必须实现至少一个接口。运行时,JVM会动态生成一个实现目标接口的代理类,代理类的方法调用会转发到InvocationHandlerinvoke方法中,在该方法中可嵌入增强逻辑并调用目标方法。

在这里插入图片描述
示例代码
// 1. 定义接口publicinterfaceUserService{voidaddUser(String name);}// 2. 实现目标类publicclassUserServiceImplimplementsUserService{@OverridepublicvoidaddUser(String name){System.out.println("添加用户:"+ name);}}// 3. 实现InvocationHandler(增强逻辑)publicclassLogInvocationHandlerimplementsInvocationHandler{privateObject target;// 目标类引用publicLogInvocationHandler(Object target){this.target = target;}// 代理类的所有方法调用都会触发invoke@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{// 增强逻辑:前置日志System.out.println("方法"+ method.getName()+"开始执行,参数:"+Arrays.toString(args));// 调用目标方法Object result = method.invoke(target, args);// 增强逻辑:后置日志System.out.println("方法"+ method.getName()+"执行结束");return result;}}// 4. 生成代理类并测试publicclassJdkProxyTest{publicstaticvoidmain(String[] args){// 目标对象UserService target =newUserServiceImpl();// 生成代理对象(需传入类加载器、目标接口、InvocationHandler)UserService proxy =(UserService)Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(),newLogInvocationHandler(target));// 调用代理方法 proxy.addUser("张三");}}
优缺点
  • 优点:基于JDK原生API,无需依赖第三方库,轻量化;
  • 缺点:目标类必须实现接口,无法代理无接口的类。

2. CGLIB动态代理(基于子类)

原理

CGLIB(Code Generation Library)是一个第三方字节码生成库,通过生成目标类的子类作为代理类,无需目标类实现接口。其核心是MethodInterceptor接口,代理类的方法调用会被拦截到intercept方法中,在此处嵌入增强逻辑并调用目标方法。

示例代码(需引入CGLIB依赖)
<!-- Maven依赖 --><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version></dependency>
// 1. 目标类(无需实现接口)publicclassOrderService{publicvoidcreateOrder(String orderId){System.out.println("创建订单:"+ orderId);}}// 2. 实现MethodInterceptor(增强逻辑)publicclassLogMethodInterceptorimplementsMethodInterceptor{// 拦截代理类方法调用@OverridepublicObjectintercept(Object o,Method method,Object[] args,MethodProxy methodProxy)throwsThrowable{// 增强逻辑:前置日志System.out.println("方法"+ method.getName()+"开始执行,参数:"+Arrays.toString(args));// 调用目标方法(推荐用methodProxy.invokeSuper,避免递归调用)Object result = methodProxy.invokeSuper(o, args);// 增强逻辑:后置日志System.out.println("方法"+ method.getName()+"执行结束");return result;}}// 3. 生成代理类并测试publicclassCglibProxyTest{publicstaticvoidmain(String[] args){// CGLIB核心类:EnhancerEnhancer enhancer =newEnhancer();// 设置父类(目标类) enhancer.setSuperclass(OrderService.class);// 设置方法拦截器 enhancer.setCallback(newLogMethodInterceptor());// 生成代理对象(子类实例)OrderService proxy =(OrderService) enhancer.create();// 调用代理方法 proxy.createOrder("ORDER_001");}}
优缺点
  • 优点:无需目标类实现接口,可代理任意类(除final类和final方法);
  • 缺点:依赖第三方库,生成代理类时需操作字节码,性能略低于JDK动态代理(JDK 8后差距已缩小)。

三、JDK与CGLIB动态代理对比

对比维度JDK动态代理CGLIB动态代理
依赖JDK原生API(无第三方依赖)需引入CGLIB库
代理原理实现目标接口生成目标类子类
目标类要求必须实现接口无接口要求(不能是final类)
方法限制仅代理接口中的方法不能代理final方法
性能(JDK 8+)生成快,调用效率高生成慢,调用效率略低

四、实际应用场景

  1. Spring AOP:默认优先使用JDK动态代理(目标类有接口时),无接口时使用CGLIB;
  2. 日志记录:统一记录方法的入参、出参、执行时间;
  3. 权限控制:方法调用前校验用户权限,无权限则抛出异常;
  4. 事务管理:方法执行前开启事务,执行后提交/回滚事务。

五、总结

动态代理是Java中“解耦横切逻辑”的核心技术,JDK动态代理和CGLIB各有适用场景:若目标类已实现接口,优先选择JDK动态代理(轻量化、无依赖);若目标类无接口或需代理类的所有方法,选择CGLIB。


如果我的内容对你有帮助,请 点赞 , 评论 , 收藏 。创作不易,大家的支持就是我坚持下去的动力!

在这里插入图片描述

Read more

Spring Boot 4使用Opentelemetry OTLP协议快速集成Jaeger + Prometheus + loki 实现指标监控,链路追踪,日志聚合

Spring Boot 4使用Opentelemetry OTLP协议快速集成Jaeger + Prometheus + loki 实现指标监控,链路追踪,日志聚合

效果图: 描述 在现代云原生架构中,可观测性不再是可选项,而是一项基本要求。你需要通过指标了解应用程序的运行情况,通过跟踪了解请求的流向,并通过日志了解应用程序的运行状态。 什么是Opentelemetry 官方:https://opentelemetry.io OpenTelemetry(简称 OTel) 是一个开源的、厂商中立的 可观测性(Observability)框架和工具集,旨在统一和标准化应用程序的 指标(Metrics)、日志(Logs)和分布式追踪(Traces) 的生成、收集、处理与导出。 它由 Cloud Native Computing Foundation(CNCF) 托管,是目前云原生生态中最主流、最推荐的可观测性标准,被广泛用于微服务、Kubernetes、Serverless 等现代架构中。 为什么使用Jaeger,Prometheus,Loki Jaeger官方描述与安装:https://www.

By Ne0inhk
分布式 vs 微服务:别再傻傻分不清了

分布式 vs 微服务:别再傻傻分不清了

分布式 vs 微服务:别再傻傻分不清了 🤔 * 引言:一对容易混淆的"双胞胎" * 一、核心定义:完全不同的维度 📚 * 1.1 什么是分布式系统? * 1.2 什么是微服务? * 二、核心区别:目标 vs 形态 🎯 * 2.1 对比表 * 2.2 用一个例子说清楚 * 2.3 代码层面的区别 * 三、分布式系统的常见形态 🏗️ * 3.1 分布式计算 * 3.2 分布式存储 * 3.3 分布式缓存 * 3.4 微服务架构 * 四、两者关系:维恩图 📊 * 五、

By Ne0inhk
SpringBoot + LangChain4j 打造企业级 RAG 智能知识库,多工具集成方案

SpringBoot + LangChain4j 打造企业级 RAG 智能知识库,多工具集成方案

基于 Spring Boot 4 + LangChain4j 1.11 + Ollama + Qdrant +MCP 的一体化 多Agentic 智能体,RAG 系统 本文结合笔者企业级项目,重新抽象,开发,一个真正“开箱即用”的企业级智能知识库系统。它不仅支持标准 RAG 问答,更融合了 Agentic 智能体架构、MCP 文件沙盒、金融专用算子 和 混合模型路由,提供从文档上传到复杂推理的完整闭环体验。 1. 总览:技术栈与核心能力 ✨ 维度技术选型能力说明后端框架Spring Boot 4 + SQLite轻量级持久化,无需额外数据库,生产可切换为其他数据,如mysql,pgsqlAI 引擎LangChain4j 1.11支持 Agentic 工具调用、流式响应、

By Ne0inhk

【GitHub项目推荐--ZeroClaw:零开销、零妥协的Rust原生AI助手基础设施】⭐⭐⭐

简介 ZeroClaw 是一个由ZeroClaw Labs开发的开源、快速、小型且完全自主的AI助手基础设施框架,采用100% Rust编写,秉持“零开销、零妥协”的设计哲学。该项目以其惊人的资源效率著称——能够在仅10美元的硬件上运行,内存占用低于5MB,启动时间短于10毫秒,相比同类解决方案(如OpenClaw)减少99%的内存使用和98%的部署成本。ZeroClaw不仅是一个高性能的AI助手运行时,更是一个完全可插拔的架构,允许开发者“在任何地方部署,交换任何组件”。 核心价值: * 极致效率:3.4MB的独立二进制文件,<5MB内存占用,<10ms启动时间 * 成本革命:专为边缘设备和资源受限环境设计,大幅降低AI助手部署门槛 * 完全自主:内置自治引擎,支持从监督到完全自主的不同运行模式 * 架构灵活:基于trait的模块化设计,所有核心子系统均可热插拔替换 技术定位:ZeroClaw填补了高性能AI助手框架与资源受限环境之间的空白。它既不是另一个“重型”AI平台,也不是简单的脚本工具,而是一个经过精心设计、

By Ne0inhk