动态代理和静态代理的区别

ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花

代理模式是Java开发中常用的设计模式,核心作用是通过代理对象间接访问目标对象,实现功能增强、权限控制、日志打印、事务管理等非业务逻辑的解耦。根据代理类的生成时机和实现方式,分为静态代理动态代理,二者在开发效率、扩展性、底层原理上存在本质差异。

一、静态代理:编译期硬编码的固定代理

1. 核心定义

静态代理是在代码编译阶段,由开发者手动编写代理类源码,代理类和目标类实现同一个接口、持有目标对象引用,最终和目标类一起编译成class文件。代理逻辑提前写死在代码中,运行时直接调用编译好的代理类。

2. 实现特点

  • 手动编码:每个目标类都需要单独编写对应的代理类,代理类与目标类一一绑定
  • 编译期生成:代理类.java文件提前编写,javac编译后生成固定的代理类.class
  • 接口绑定:必须和目标类实现相同的接口,通过接口调用目标方法

3. 典型优缺点

优点:实现简单、直观,不需要依赖第三方框架,小场景下易调试;

缺点:代码冗余度极高,新增目标类/新增增强逻辑都要修改代理类,扩展性极差,不适合大规模业务开发。

二、动态代理:运行期动态生成的灵活代理

1. 核心定义

动态代理无需手动编写代理类源码,在程序运行阶段通过Java反射机制(JDK动态代理)或字节码生成技术(CGLIB动态代理),动态创建代理类对象并加载到JVM。代理逻辑统一封装,无需针对每个目标类单独开发,实现横切逻辑的复用。

2. 主流实现方案

  • JDK动态代理:Java原生支持,基于接口实现,目标类必须实现接口,通过InvocationHandler调用目标方法
  • CGLIB动态代理:第三方字节码框架,基于继承实现,无需目标类实现接口,通过生成目标类子类作为代理类

3. 核心特点

无手动代理类源码、运行时动态生成、一套增强逻辑可适配多个目标类、横切功能(日志、事务)可统一封装,彻底解耦业务与非业务代码。

三、静态代理 vs 动态代理:核心维度对比

代理类生成时机

编译期(提前编写.java文件,编译成.class)

运行期(JVM加载时动态生成字节码,无源码文件)

代码编写方式

手动硬编码,代理类与目标类一一对应

无需编写代理类,通过反射/字节码自动生成

代码复用性

极差,增强逻辑分散,无法复用

极强,一套增强逻辑适配所有目标类

灵活性

极低,新增方法/目标类需重写代理类

极高,动态适配目标类,无需修改原有代码

扩展性

差,维护成本高,不适合复杂场景

优,支持统一横切扩展,适配大规模项目

依赖要求

无第三方依赖,纯原生代码

JDK代理需接口,CGLIB需引入第三方包

运行性能

略高,无反射开销,直接调用

略低,存在反射/字节码生成开销(可忽略)

适用场景

目标类少、逻辑固定、简单业务场景

框架开发、AOP切面、事务管理、日志统一处理等复杂场景

四、关键总结:一句话分清二者

静态代理是“提前造好的固定工具”,针对性强但通用性差;动态代理是“运行时按需造工具”,通用性极强、扩展性拉满,是Spring AOP等主流框架的核心底层实现。

ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花

Spring 文章被收录于专栏

本专栏聚焦Spring全生态体系,从IoC/AOP核心原理入手,覆盖Spring Boot自动配置、事务管理、Web开发等实战内容。拆解循环依赖、动态代理等高频面试难点,助力开发者从入门到精通,打通单体到微服务的技术链路,解决企业级开发痛点,提升架构设计与问题排查能力,成为Java后端进阶的必备技术专栏。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务