背景 Arthas 是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。
https://github.com/alibaba/ar…Arthas 提供了非常丰富的关于调用拦截的命令,比如 trace/watch/monitor/tt。但是很多时候我们在排查问题时,需要更多的线索,并不只是函数的参数和返回值。比如在一个 spring 应用里,想获取到 spring context 里的其它 bean。如果能随意获取到 spring bean,那就可以“为所欲为”了。
下面介绍如何利用 Arthas 获取到 spring context。
Demo:https://github.com/hengyunabc…
Arthas 快速开始:https://alibaba.github.io/art…
使用 tt 命令获取到 spring contextDemo 是一个 spring mvc 应用,请求会经过一系列的 spring bean 处理,那么我们可以在 spring mvc 的类里拦截到一些请求。
启动 Demo:mvn spring-boot:run
使用 Arthas Attach 成功之后,执行 tt 命令来记录 RequestMappingHandlerAdapter#invokeHandlerMethod 的请求
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod 然后访问一个网页:http://localhost:8080/
可以看到 Arthas 会拦截到这个调用,index 是 1000,并且打印出:
$ watch com.example.demo.Test * ‘params[0]@sss’$ tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethodPress Ctrl+C to abort.Affect(class-cnt:1 , method-cnt:1) cost in 101 ms. INDEX TIMESTAMP COST(ms IS-RE IS-EX OBJECT CLASS METHOD
) T P
1000 2019-01-27 16:31 3.66744 true false 0x4465cf70 RequestMappingHandlerAda invokeHandlerMethod
:54 pter
那么怎样获取到 spring context?
可以用 tt 命令的 - i 参数来指定 index,并且用 - w 参数来执行 ognl 表达式来获取 spring context:
$ tt -i 1000 -w ‘target.getApplicationContext()’@AnnotationConfigEmbeddedWebApplicationContext[
reader=@AnnotatedBeanDefinitionReader[org.springframework.context.annotation.AnnotatedBeanDefinitionReader@35dc90ec],
scanner=@ClassPathBeanDefinitionScanner[org.springframework.context.annotation.ClassPathBeanDefinitionScanner@72078a14],
annotatedClasses=null,
basePackages=null,
]Affect(row-cnt:1) cost in 7 ms. 从 spring context 里获取任意 bean 获取到 spring context 之后,就可以获取到任意的 bean 了,比如获取到 helloWorldService,并调用 getHelloMessage() 函数:
$ tt -i 1000 -w ‘target.getApplicationContext().getBean(“helloWorldService”).getHelloMessage()’@String[Hello World]Affect(row-cnt:1) cost in 5 ms. 更多的思路在很多代码里都有 static 函数或者 static holder 类,顺滕摸瓜,可以获取很多其它的对象。比如在 Dubbo 里通过 SpringExtensionFactory 获取 spring context:
$ ognl ‘#context=@com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@contexts.iterator.next,
#context.getBean(“userServiceImpl”).findUser(1)’
@User[
id=@Integer[1],
name=@String[Deanna Borer],
]
本文作者:横云断岭
阅读原文
本文为云栖社区原创内容,未经允许不得转载。