本文章的产生是对一个bug的总结,是一次自底向上的记录,并不打算有一个全局的认识,以后有机会可以系统分析。
git地址:github.com/fw103699437…
bug展示
application.yml内容
num: 0010
代码
@Autowired
Environment environment;
@Login
@RequestMapping("/method")
public Entity method(@LoginUser Entity entity, @RequestBody Entity entity1){
System.out.println(environment.getProperty("num"));
return entity;
}
结果
8
能看到环境里的属性与yml配置文件里的属性不一致
项目里配置文件并不是10,这里做了一些简化,可以很容易猜测到,应该是读取的时候,把0010当作八进制了
bug trace
话不多说,直接上图,如果不够清晰,可以点击链接 www.processon.com/view/link/5…
大致流程就是:
1:容器启动
2:触发监听
3:响应监听读取配置
4:利用snakeyaml来解析yml
5:解析map键值对
6:解析map的value(此时出了问题)
出问题的代码如下
public class ConstructYamlInt extends AbstractConstruct {
@Override
public Object construct(Node node) {
String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");
int sign = +1;
char first = value.charAt(0);
if (first == '-') {
sign = -1;
value = value.substring(1);
} else if (first == '+') {
value = value.substring(1);
}
int base = 10;
if ("0".equals(value)) {
return Integer.valueOf(0);
} else if (value.startsWith("0b")) {
value = value.substring(2);
base = 2;
} else if (value.startsWith("0x")) {
value = value.substring(2);
base = 16;
//因为我们是0010,因此进入这里,base即进制
} else if (value.startsWith("0")) {
value = value.substring(1);
base = 8;
} else if (value.indexOf(':') != -1) {
String[] digits = value.split(":");
int bes = 1;
int val = 0;
for (int i = 0, j = digits.length; i < j; i++) {
val += Long.parseLong(digits[j - i - 1]) * bes;
bes *= 60;
}
return createNumber(sign, String.valueOf(val), 10);
} else {
return createNumber(sign, value, 10);
}
return createNumber(sign, value, base);
}
}

解决
既然看到了出问题的地方,那么就只要让value不以0开头就好了,拿双引号括起来就好了。(或者不用yml?哈哈哈哈)
加双引号之后
0010
改为properties之后
0010
想法
以后可以补一下spring监听机制和加载文件(包括系统属性、bootstrap/application,properties/yml的区别之类的)