4

I am experimenting with Google Guice (3.0) and Google Reflections (0.9.6).

I have the following files:

Operation.java:

package com.company1.calculator;

public interface Operation {
    public int apply(int a, int b);
}

Addition.java:

package com.company1.calculator;

public class Addition implements Operation {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
}

Other various "operation" classes spread across multiple packages.

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);
        }
    }
}

Calculator.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));
        }
    }
}

And finally, 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);
    }
}

After executing App.java inside of IntelliJ I get the following output, as expected:

Calculator: 3 3
Modulus: 0
Division: 1
Multiplication: 9
Addition: 6

However, when I package this application as a jar I only get the following output:

Calculator: 3 3

Why is this and how can I fix it? The closest thing I found was Issue 48, but that says fixed as of May 2011. Surely that would have made it into Maven by now...

4

1 回答 1

2

我能够完全按照描述重现这一点。问题似乎是默认的 Reflections 构造函数试图在磁盘上找到可以找到每个给定参数的位置。当在 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),但性能会受到影响。

于 2012-07-05T17:49:46.580 回答