Java常用动态代理类库与Proxy

发布时间 - 2026-01-06 00:00:00    点击率:
Java动态代理核心是Proxy类必须配合InvocationHandler使用,后者决定方法调用行为;Proxy仅生成代理对象,不执行逻辑;代理仅支持接口,无接口时需CGLIB、Javassist或Byte Buddy等字节码增强方案。

Java动态代理核心:Proxy类必须配合InvocationHandler使用

Java原生Proxy类本身不执行代理逻辑,它只是生成代理对象的工厂。真正决定方法调用行为的是你传入的InvocationHandler实现。没有自定义InvocationHandlerProxy.newProxyInstance()生成的对象调用任何方法都会抛NullPointerException(如果handler为null)或直接失败。

常见错误是只写Proxy.newProxyInstance(...)却忘了实现invoke()方法,或者在invoke()里漏掉method.invoke(target, args)导致目标方法完全没执行。

  • 必须实现InvocationHandler接口,并在invoke()中显式调用目标对象方法(除非你有意拦截)
  • Proxy.newProxyInstance()第三个参数不能为null,否则运行时报NullPointerException
  • 代理对象只能对接口生效,不能代理具体类(这是JDK Proxy的根本限制)

CGLIB和Javassist适合代理没有接口的类

当目标类没有实现任何接口时,Proxy彻底失效。这时需要字节码增强类库:CGLIB(基于ASM)和Javassist(API更友好)。它们通过继承目标类生成子类实现代理,因此目标类不能是final,方法也不能是finalprivate

CGLIB性能通常略优于Javassist,但配置稍重;Javassist支持运行时编写Java语法风格的逻辑(比如用insertBefore()注入代码),调试更直观。

  • CGLIB依赖net.sf.cglib.proxy.Enhancer,需设置setSuperclass()setCallback()
  • Javassist需先获取CtClass,再用instrument()toBytecode()操作字节码
  • Spring AOP默认优先用Proxy,只有目标类无接口时才自动fallback到CGLIB

Byte Buddy是现代替代方案,API更安全、更易读

相比CGLIB和Javassist,Byte Buddy设计上规避了许多运行时陷阱:它默认拒绝增强final类/方法(可显式配置覆盖),内置校验机制,且API以DSL形式组织,意图清晰。例如.method(ElementMatchers.any()).intercept(...)比CGLIB的FixedValueMethodInterceptor更贴近语义。

它不依赖运行时反射解析,编译期检查更强,出错提示也更明确(比如直接告诉你哪个方法因final被跳过)。Spring 6+已将Byte Buddy作为AOP底层候选之一。

  • 无需手动处理ClassLoadernew ByteBuddy().subclass(...)自动适配
  • 拦截逻辑用Implementation封装,支持MethodDelegationAdvice两种模式
  • 对Java 17+的密封类(sealed class)和模块系统兼容性更好

选型关键看三点:有没有接口、是否允许继承、是否需要编译期保障

不是越新越好,也不是越快越好。如果项目只代理接口,Proxy零依赖、无额外jar、线程安全,就是最优解;如果必须代理final工具类,那CGLIB/Javassist/Byte Buddy全都不行——只能改源码或换设计。

容易被忽略的是类加载器问题:CGLIB生成的子类默认使用目标类的ClassLoader,但在OSGi或热部署场景下,若代理类与目标类不在同一ClassLoader,会报ClassNotFoundExceptionIllegalAccessError。Byte Buddy对此有显式ClassLoadingStrategy控制,而原生Proxy要求所有接口必须能被指定ClassLoader加载。

Proxy.newProxyInstance(
    target.getClass().getClassLoader(), // 这个ClassLoader必须能看见所有接口
    target.getClass().getInterfaces(),
    new MyInvocationHandler(target)
);


# java  # 字节  # access  # 工具  # ssl  # proxy  # 动态代理 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 香港服务器租用每月最低只需15元?  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  手机软键盘弹出时影响布局的解决方法  利用python获取某年中每个月的第一天和最后一天  敲碗10年!Mac系列传将迎来「触控与联网」双革新  如何快速搭建二级域名独立网站?  网站制作企业,网站的banner和导航栏是指什么?  Laravel怎么实现模型属性的自动加密  南京网站制作费用,南京远驱官方网站?  Laravel Docker环境搭建教程_Laravel Sail使用指南  Laravel定时任务怎么设置_Laravel Crontab调度器配置  Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程  在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?  如何在云指建站中生成FTP站点?  EditPlus中的正则表达式 实战(1)  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】  如何在阿里云虚拟服务器快速搭建网站?  悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  长沙企业网站制作哪家好,长沙水业集团官方网站?  ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】  Laravel怎么使用Intervention Image库处理图片上传和缩放  如何在建站之星绑定自定义域名?  打造顶配客厅影院,这份100寸电视推荐名单请查收  车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?  个人摄影网站制作流程,摄影爱好者都去什么网站?  js实现点击每个li节点,都弹出其文本值及修改  如何用已有域名快速搭建网站?  专业商城网站制作公司有哪些,pi商城官网是哪个?  中国移动官方网站首页入口 中国移动官网网页登录  Android实现代码画虚线边框背景效果  零服务器AI建站解决方案:快速部署与云端平台低成本实践  米侠浏览器网页图片不显示怎么办 米侠图片加载修复  简历没回改:利用AI润色让你的文字更专业  如何确保FTP站点访问权限与数据传输安全?  佛山网站制作系统,佛山企业变更地址网上办理步骤?  Linux安全能力提升路径_长期防护思维说明【指导】  如何确认建站备案号应放置的具体位置?  HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  Laravel Octane如何提升性能_使用Laravel Octane加速你的应用  CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】  Laravel如何集成第三方登录_Laravel Socialite实现微信QQ微博登录  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法  Bootstrap整体框架之CSS12栅格系统  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】  网站制作报价单模板图片,小松挖机官方网站报价?