我正在试用Google Guice(3.0)和Google Reflections(0.9.6)。
我有以下文件:
操作.java:
package com.company1.calculator;
public interface Operation {
public int apply(int a, int b);
}
添加.java:
package com.company1.calculator;
public class Addition implements Operation {
@Override
public int apply(int a, int b) {
return a + b;
}
}
其他各种各样的"操作"类分布在多个包中
CalculatorModule.java:
package com.company1.calculator;
import com.google.inject.AbstractModule;
import com.google.inject.multibindings.MapBinder;
import org.reflections.Reflections;
public class CalculatorModule extends AbstractModule {
@Override
protected void configure() {
Reflections reflections = new Reflections("");
MapBinder<String, Operation> map = MapBinder.newMapBinder(binder(), String.class, Operation.class);
for (Class<? extends Operation> o : reflections.getSubTypesOf(Operation.class)) {
map.addBinding(o.getSimpleName()).to(o);
}
}
}
计算器.java:
package com.company1.calculator;
import com.google.inject.Inject;
import java.util.Map;
public class Calculator {
private Map<String, Operation> operations;
@Inject
public Calculator(Map<String, Operation> operations) {
this.operations = operations;
}
public void printCalculations(int a, int b) {
System.out.println("Calculator: " + a + " " + b);
for (String s : operations.keySet()) {
System.out.print(s + ": ");
System.out.println(operations.get(s).apply(a, b));
}
}
}
最后,App.java:
package com.company1.calculator;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class App {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new CalculatorModule());
Calculator c = injector.getInstance(Calculator.class);
c.printCalculations(3, 3);
}
}
在IntelliJ内部执行App.java后,我得到了如下输出,正如预期的那样:
计算器:3 3
模量:0
部门:1
乘法:9
添加:6
然而,当我将这个应用程序打包为jar时,我只得到以下输出:
计算器:3 3
为什么会这样?我该如何修复?我发现的最接近的是第48期,但据说截至2011年5月已修复。现在肯定已经进入Maven了。。。
我能够完全按照描述复制它。问题似乎是默认的反射构造函数试图在磁盘上找到每个给定参数的位置。当在IDE中传递"时,它会找到/bin目录,当从/tmp/so8780228.jar运行时,它将找到/tmp/(ConfigurationBuilder.java:87处的断点)
简单的解决方法是提供"以外的内容,这不会给配置构建提供有用的信息,而是提供可以在一个位置找到的类似"com.company1"的内容。
Reflections reflections = new Reflections("com.company1");
在这种情况下,ConfigurationBuilder会正确地找到要扫描的路径/tmp/so8780228.jar,并且一切正常。
或者,您可以与ConfigurationBuilder进行更多的交互,并告诉它搜索类路径上的每个jar(例如,迭代System.getProperty(java.class.path)并添加每个jar),但性能会受到影响。