当前位置: 首页 > news >正文

详细介绍:【从0开始学习Java | 第23篇】动态代理

详细介绍:【从0开始学习Java | 第23篇】动态代理

在这里插入图片描述

文章目录

  • Java动态代理概述
    • 一、动态代理的核心概念
      • 形象解释
    • 二、两种主流动态代理实现
      • 1. JDK动态代理(基于接口)
        • 原理
        • 示例代码
        • 优缺点
      • 2. CGLIB动态代理(基于子类)
        • 原理
        • 示例代码(需引入CGLIB依赖)
        • 优缺点
    • 三、JDK与CGLIB动态代理对比
    • 四、实际应用场景
    • 五、总结

Java动态代理概述

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

在这里插入图片描述

一、动态代理的核心概念

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

在这里插入图片描述

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

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

形象解释

在这里插入图片描述

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

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

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

原理

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

在这里插入图片描述

示例代码
// 1. 定义接口
public interface UserService {
void addUser(String name);
}
// 2. 实现目标类
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
}
// 3. 实现InvocationHandler(增强逻辑)
public class LogInvocationHandler implements InvocationHandler {
private Object target; // 目标类引用
public LogInvocationHandler(Object target) {
this.target = target;
}
// 代理类的所有方法调用都会触发invoke
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 增强逻辑:前置日志
System.out.println("方法" + method.getName() + "开始执行,参数:" + Arrays.toString(args));
// 调用目标方法
Object result = method.invoke(target, args);
// 增强逻辑:后置日志
System.out.println("方法" + method.getName() + "执行结束");
return result;
}
}
// 4. 生成代理类并测试
public class JdkProxyTest {
public static void main(String[] args) {
// 目标对象
UserService target = new UserServiceImpl();
// 生成代理对象(需传入类加载器、目标接口、InvocationHandler)
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new LogInvocationHandler(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. 目标类(无需实现接口)
public class OrderService {
public void createOrder(String orderId) {
System.out.println("创建订单:" + orderId);
}
}
// 2. 实现MethodInterceptor(增强逻辑)
public class LogMethodInterceptor implements MethodInterceptor {
// 拦截代理类方法调用
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 增强逻辑:前置日志
System.out.println("方法" + method.getName() + "开始执行,参数:" + Arrays.toString(args));
// 调用目标方法(推荐用methodProxy.invokeSuper,避免递归调用)
Object result = methodProxy.invokeSuper(o, args);
// 增强逻辑:后置日志
System.out.println("方法" + method.getName() + "执行结束");
return result;
}
}
// 3. 生成代理类并测试
public class CglibProxyTest {
public static void main(String[] args) {
// CGLIB核心类:Enhancer
Enhancer enhancer = new Enhancer();
// 设置父类(目标类)
enhancer.setSuperclass(OrderService.class);
// 设置方法拦截器
enhancer.setCallback(new LogMethodInterceptor());
// 生成代理对象(子类实例)
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。


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

在这里插入图片描述

http://www.jsqmd.com/news/45949/

相关文章:

  • 安卓中执行 root 命令
  • UniApp缓存系统详解 - 详解
  • FreeSWITCH使用mod_fail2ban模块来提升安全
  • 【ArcMap】使用拓扑(Topology)检查线是否存在断点
  • 电动汽车行业时序数据库选型指南:以 TDengine 为例的四大关键维度与评估标准
  • CF2165 VP 记录
  • 如何在SPM混编中实现不同target之间的通信?
  • Python在线教育广告精准投放:SEM结构方程、XGBoost、KDE核密度、聚类、因子分析、随机森林集成优化融合用户满意度渠道效能|附代码数据
  • 完整教程:Spring Boot Actuator全解析
  • 专题:2025年AI Agent智能体行业价值及应用分析报告:技术落地与风险治理|附140+ 份报告PDF、数据、可视化模板汇总下载
  • 2025/11/20-Why brushing teeth twice a day is not always best
  • uos安装idea
  • HDU3586-Information Disturbing
  • 【App Service】.NET 应用在App Service上内存无法占用100%的问题原因
  • 深入解析:css 的 clip-path 属性,绘制气泡
  • 快速构建一个基础、现代化的 WinForm 管理系统!
  • 国内外研究现状全面解析:掌握学术前沿的必备指南
  • 费马小定理在素数检测中的应用
  • 把 1688 商品详情「搬进 MySQL」:Java 爬虫全链路实战(2025 版) - 实践
  • 深入解析:从传统架构到云原生,如何应对数据增长挑战?
  • 50036_基于微信小程序的智能点餐推荐系统
  • 【NAOI】题解
  • Windows系统基础安全浅谈
  • 深入解析:医疗多模态共情推理与学习一体化网络Python实现(2025扩充版)
  • curl/libcurl SMTP CRLF注入漏洞深度分析
  • 2025年11月氨基酸水溶肥,花芽分化氨基酸水溶肥,低温酶解氨基酸水溶肥厂家最新推荐,权威测评与种植选择指南!
  • 2025年11月沣硕40+中微量元素水溶肥,防裂果中微量元素水溶肥,促花稳果中微量元素水溶肥厂家推荐:规模化种植适配品牌
  • 4.6.4版本闪亮登场~赶快了解一下新内容吧
  • 2025年11月花芽分化氨基酸水溶肥,膨果上色氨基酸水溶肥,高含量氨基酸水溶肥厂家推荐,实测促产效果与品牌解析!
  • XMind for Mac v24.01.dmg 安装教程(Mac思维导图软件下载安装步骤)