获取 Spring 应用上下文
使用工具类
如果你的项目中有一个工具类实现了 ApplicationContextAware
接口,如 cn.shutdown.pf.utils.SpringContextUtils
,可以使用该类获取 ApplicationContext
:
@Component
public final class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
使用 OGNL 获取
在 Arthas 中,使用 ognl
命令结合工具类获取 ApplicationContext
:
ognl -c <classLoaderHash> '#context=@cn.shutdown.pf.performance.utils.SpringContextUtils@getApplicationContext()'
获取类加载器哈希值
使用 sc
命令
在 Arthas 中,使用 sc
命令可以查看类的详细信息,包括类加载器的哈希值。例如,查看 SpringContextUtils
类的类加载器哈希值:
sc -d cn.shutdown.pf.performance.utils.SpringContextUtils
输出示例:
class-info cn.shutdown.pf.performance.utils.SpringContextUtils
code-source nested:/app/web.jar/!BOOT-INF/classes/!
name cn.shutdown.pf.performance.utils.SpringContextUtils
...
class-loader +-org.springframework.boot.loader.launch.LaunchedClassLoader@660591fb
+-jdk.internal.loader.ClassLoaders$AppClassLoader@251a69d7
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@89c10b7
classLoaderHash 660591fb
在输出中,classLoaderHash
字段显示了类加载器的哈希值,这里是 660591fb
。
使用 ognl
命令
你也可以使用 ognl
命令直接获取类加载器的哈希值。例如:
ognl '@cn.shutdown.pf.performance.utils.SpringContextUtils@getClass().getClassLoader().hashCode()'
这将返回类加载器的哈希值。
调用 Bean 方法
调用无参数方法
获取到 ApplicationContext
后,可以获取 Bean 并调用其无参数方法:
ognl -c <classLoaderHash> '#context=@cn.shutdown.pf.performance.utils.SpringContextUtils@getApplicationContext(), #bean=#context.getBean("brokerService"), #bean.someMethod()'
调用有参数方法
如果方法有参数,直接在调用时传入参数值:
ognl -c <classLoaderHash> '#context=@cn.shutdown.pf.performance.utils.SpringContextUtils@getApplicationContext(), #bean=#context.getBean("brokerService"), #bean.orderChildPay("CYD2024122923468019")'
调用方法并传入对象参数
当方法需要一个对象作为参数时,需要在 OGNL 表达式中创建该对象并设置其属性:
ognl -c <classLoaderHash> '#context=@cn.shutdown.pf.utils.SpringContextUtils@getApplicationContext(), #param=new com.yourpackage.BrokerOrderChildUpdateMqParam(), #param.setChildNo("DD2024122923468019"), #param.setOrderNo("12345"), #bean=#context.getBean("brokerServiceImpl"), #bean.orderChildPay(#param)'
查看 Spring Bean 名称
使用 vmtool
命令
如果你的 Arthas 支持 vmtool
命令,可以使用以下命令查看所有注册的 Bean 名称:
vmtool --action getInstances --className org.springframework.context.ApplicationContext --express 'instances[0].getBeanDefinitionNames()'
使用 ognl
命令
如果不支持 vmtool
命令,可以使用 ognl
命令结合 ApplicationContext
获取 Bean 名称:
ognl -c <classLoaderHash> '#context=@cn.shutdown.pf.utils.SpringContextUtils@getApplicationContext(), #context.getBeanDefinitionNames()'
常见问题及解决方法
ClassNotFoundException
- 确保类路径正确,类已编译并打包到应用中。
- 使用
sc
命令检查类加载器信息,确保使用正确的类加载器。
NoSuchBeanDefinitionException
- 确认 Bean 名称正确,检查类上的注解(如
@Component
、@Service
)。 - 确保 Spring 组件扫描路径包含了 Bean 类所在的包路径。
- 使用 Arthas 的
bean
命令(如果支持)或ognl
命令列出所有 Bean 名称,确认 Bean 是否存在。
方法调用返回 null
- 方法逻辑导致返回
null
,检查方法内部逻辑和业务条件。 - 方法业务逻辑设计为返回
null
,需要根据业务需求处理返回值。
注意事项
- 确保 Arthas 版本与操作系统和应用架构兼容。
- 使用正确的类加载器哈希值,可以通过
sc
命令获取。 - 调用方法时,确保方法签名与传入的参数类型和数量匹配。
- 在生产环境中使用 Arthas 时,注意安全和性能影响,谨慎操作。