关于类持有静态变量而引发的问题排查
问题描述
闲话少叙,先上代码。
public function main() {
Util util = new Util();
util.print();
}
public class Util {
public static provider = new Provider();
public Util() {
# do sth
}
public void print() {
# print sth
}
}
public function Provider() {
public Provider() {
loadData();
}
private void loadData() {
# load data
}
}
大概使用逻辑是这样,在调用入口,实例化Util对象并调用他的print方法。 这个时候,获取到了一个runtime exception:class Util not defined。
类明明就摆在那里,为什么会报异常呢? 大家如果了解了类静态成员变量的初始化过程,就一眼看出来问题。
首先,provider是在Util类被加载的时候初始化的,要早于Util的实例化。
其次,如果provider初始化失败,会导致Util类加载失败,在实例化的时候就会抛异常。
问题的直接原因是在Provider的构造过程,由于构造函数执行了loadData的动作,这里就存在一些不确定因素,会导致错误的发生,从而影响到了Util的加载。
改进思路
精简类初始化的过程,优先保证对象能实例化成功,从而再执行数据加载的逻辑。可以利用Spring的PostConstruct注解来实现实例化和数据加载动作的分离。
public function main() {
Util util = new Util();
util.print();
}
public class Util {
@Resource
public Provider provider;
public Util() {
# do sth
}
public void print() {
# print sth
}
}
@Component
public function Provider() {
@PostConstruct
private void loadData() {
# load data
}
}
这样,就将问题暴露在运行时,就不会将问题隐藏的那么深了。
总结一下,
第一,尽量不要在构造函数里执行太多的业务逻辑,以及数据初始化的动作。
第二,对象示例谨慎持有静态数据。