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

使用Arthas监听Spring代理对象

一、Arthas监听代理对象的核心原理

  1. 动态代理与字节码增强
    Spring的AOP代理(JDK动态代理或CGLIB)会生成新类:

    • JDK代理:基于接口,生成$ProxyX类(如$Proxy43)[2]。
    • CGLIB代理:通过继承目标类生成子类(如TargetClass$$EnhancerBySpringCGLIB$$xxxx),嵌入拦截器链(如DynamicAdvisedInterceptor)[3][5]。
    • Arthas通过反编译这些类,可视化增强逻辑(如事务拦截器TransactionInterceptor)。
  2. 关键机制

    • 代理对象持有原始对象的引用(通过TargetSource获取)[2][8]。
    • 调用代理方法时,实际执行的是拦截器链(Advisor链)[12]。

二、Arthas操作步骤
步骤1:定位代理类

查找被代理的类(示例:UserService)
sc *UserService输出示例:
com.example.UserService$$EnhancerBySpringCGLIB$$123abc 
  • 若结果为$ProxyX(JDK代理)或$$EnhancerBySpringCGLIB$$(CGLIB代理),说明是代理类[1][3]。

步骤2:反编译代理类字节码

反编译CGLIB代理类 
jad com.example.UserService$$EnhancerBySpringCGLIB$$123abc 
  • 查看反编译代码中的方法拦截逻辑(如intercept()方法中的MethodInterceptor调用链)[3][7]。

步骤3:获取原始目标对象

获取代理对象实例的ID(需先执行调用触发类加载)
vmtool --action getInstances --className com.example.UserService$$EnhancerBySpringCGLIB$$123abc 通过OGNL获取原始对象(假设实例ID为@12345)
ognl '@com.example.UserService@12345.target.targetSource.target'
  • 原理:
    Spring代理对象实现了Advised接口,其TargetSource持有原始Bean[2][8]。

步骤4:监听方法调用

监听代理类的指定方法(如save方法)
watch com.example.UserService$$EnhancerBySpringCGLIB$$123abc save '{params, target, returnObj}' -x 3 
  • 参数说明:
    params(方法入参)、target(代理对象本身)、returnObj(返回值)[1][6]。

三、常见问题解决

  1. 事务失效(自调用问题)

    • 现象:Service内部方法A调用方法B,B的事务不生效。
    • 原因:自调用不走代理,因此未触发拦截器链。
    • 解决:
      // 在方法A中获取当前代理对象调用B 
      UserService proxy = (UserService) AopContext.currentProxy();
      proxy.methodB();
      
      需在启动类加@EnableAspectJAutoProxy(exposeProxy = true)[11]。
  2. Private方法代理异常

    • CGLIB无法代理private/final方法,调用时会直接执行原始方法(无增强逻辑),若方法依赖Spring注入的Bean,会因未初始化导致NPE[9]。
  3. 动态切换数据源失效

    • 若通过@Transactional注解管理事务,事务代理会优先于数据源切换执行,导致切换失效。需调整AOP顺序或手动管理事务[4]。

四、最佳实践

  • 优先使用CGLIB代理:
    在Spring Boot中配置spring.aop.proxy-target-class=true,避免JDK代理的接口限制。
  • 结合Spring工具类验证:
    使用AopUtils.isCglibProxy(obj)AopTestUtils.getTargetObject(obj)辅助调试[8]。
  • 日志增强:
    对代理类方法添加trace命令,实时追踪调用栈:
    trace com.example.UserService$$EnhancerBySpringCGLIB$$123abc save 
    

生产环境建议通过ognl检查AdvisedSupport中的拦截器链,确认事务、日志等切面是否生效。


附录:Arthas命令速查

命令用途示例
sc查找类sc *Service
jad反编译类jad com.example.UserService
ognl执行表达式获取对象ognl '@springBean'
watch监听方法调用watch *Service * '{params}'
vmtool获取JVM实例vmtool -x 3 --action getInstances -c ClassName
http://www.dtcms.com/a/273147.html

相关文章:

  • 从UI设计到数字孪生实战部署:构建智慧教育的在线学习分析平台
  • Java观察者模式实现方式与测试方法
  • Constants
  • SSM 框架整合教程:从环境搭建到 CRUD 实现
  • html页面,一个控件,可以粘贴图片和样式,一直按enter键会将下面内容推下去
  • OrCAD 24.1补丁005中文界面切换指南
  • QT Android 如何打包大文件到目录下?
  • 【Pandas】pandas DataFrame from_records
  • Android开发中几种scope的对比
  • ClickHouse JSON 解析
  • Kubernetes Dashboard UI 部署安装
  • stm32计时的两个方法
  • HarmonyOS学习记录4
  • 基于U-net的高阶心音信号去噪系统设计与实现
  • SSE方式调用php,不是直接 post,
  • 【C++基础语法】
  • STM32F103之ModBus\RS232\RS422\RS485
  • 瑞幸X多邻国“疯感”营销:以情感共鸣取代硬广触达
  • Qt开发:QtConcurrent介绍和使用
  • Python正则表达式实战指南
  • 深度学习13(经典卷积网络结构+卷积网络结构优化)
  • J1939协议
  • 个体户核定多地暂停,将不再享受核定征收?
  • 人工智能-基础篇-29-什么是低代码平台?
  • 大数据学习6:Sqoop数据迁移工具
  • ArcGIS 打开 nc 降雨量文件
  • MinerU2将PDF转成md文件,并分拣图片
  • TB6612电机驱动
  • [注解: @ComponentScan]-原理分析
  • Cloudflare 发布容器服务公测版:边缘计算新时代来临?