在开发过程经常有同学问:“我这个配置更新提交了,怎么样知道项目中是否已经更新使用新值?” 常用的方法是添加日志打印该值判断是否更新。今天我们用Arthas来实现项目中配置值实时读取。
Arthas 是Alibaba开源的Java诊断工具。使用 Arthas 可以很方便帮助我们排查线上问题。下面简单介绍几个常用的命令以及使用的场景。
上面的命令是作为开发经常使用到的,具体怎么样使用Arthas请看官网。
假设大家都知道 SpringBoot 读取配置之后存在 ConfigurableApplicationContext 的 environment 中。如果有不知道的,可以在 PropertySourceBootstrapConfiguration#initialize 方法里打个断点debug调试一波?。下面用一个例子操作一波。
application.properties文件中添加 author=Greiz 键值对。
想办法拿到项目中 ApplicationContext 对象。ognl只获取静态属性,所以我们一般需要查找项目中是否存在静态的ApplicationContext对象。这里面我就自己创建了一个类来提供静态的ApplicationContext。
package com.greiz.demo.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ConfigHandler implements InitializingBean, ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(applicationContext.getEnvironment().getProperty("author"));
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ConfigHandler.applicationContext = applicationContext;
}
}
这种方式是不是到处可见。如果用Dubbo的,Dubbo框架里com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory 持有静态的 ApplicationContext 对象。
使用ognl获取静态 ApplicationContext 属性。
ognl '#context=@com.greiz.demo.config.ConfigHandler@applicationContext,#context.getEnvironment().getProperty("author")'
逗号之前是获取 ApplicationContext 对象并赋值给 context。逗号后面的获取 Environment 对象中的属性。这个 "author" 属性就是application.properties 配置的,也可以是远程的配置文件。
对应的结果
其实只要获取到ApplicationContext 对象,我们就可以对Spring容器为所欲为了,比如下面不知耻辱的行为:
@Component
public class Greiz {
@Value("${userName}")
private String name;
@Value("${userAge}")
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
可以获取Spring容器的所有bean,然后调用对应的方法。
熟悉Arthas 工具常用命令;了解配置最终所保存的对象;提供静态属性的 ApplicationContext 对象;ognl获取Spring容器钥匙ApplicationContext,然后做你们想做的事。