下面我们通过源码分析来阐述个中原理。在通过上一节分析的处理好命令行参数之后,monkeyrunner入口main函数的下一步就是去尝试根据这些参数来调用MonkeyRunnerStarter的构造函数:
178 public static void main(String[] args) {
179 MonkeyRunnerOptions options =
MonkeyRunnerOptions.processOptions(args);
180
181 if (options == null) {
182 return;
183 }
184
185
186 replaceAllLogFormatters(MonkeyFormatter.DEFAULT_INSTANCE,
options.getLogLevel());
187
188 MonkeyRunnerStarter runner =
new MonkeyRunnerStarter(options);
189 int error = runner.run();
190
191
192 System.exit(error);
193 }
194 }
代码8-3-1 初始化MonkeyRunnerStarter
其中的options参数就是上一节最后根据所有参数创建的MonkeyRunnerOptions对象,里面保存了所有的参数。往下我们进入MonkeyRunnerStarter的构造函数:
代码8-3-2 MonkeyRunnerStarter构造函数
55 public MonkeyRunnerStarter(MonkeyRunnerOptions options)
56 {
57 Map<String, String> chimp_options = new TreeMap();
58 chimp_options.put("backend", options.getBackendName());
59 this.options = options;
60 this.chimp = ChimpChat.getInstance(chimp_options);
61 MonkeyRunner.setChimpChat(this.chimp);
62 }
仅从这个方法的几行代码我们可以看到它其实做的事情就是去根据‘backend’来初始化ChimpChat 并把该实例保存到MonkeyRunnerStarter的chimp成员变量中,同时也会调用MonkeyRunner的静态方法setChimpChat把该ChimpChat对象设置到MonkeyRunner的静态成员变量里面,为什么说它一定是静态成员变量呢?因为第61行保存该实例调用的是MonkeyRunner这个类的方法,而不是一个实例,所以该方法肯定就是静态的,而一个静态方法里面的成员函数也必然是静态的。大家跳进去MonkeyRunner这个类就可以看到:
51 static void setChimpChat(ChimpChat chimp)
52 {
53 chimpchat = chimp;
54 }
代码8-3-3 MonkeyRunner - setChimpChat