4

Google Guice (3.0) と Google Reflections (0.9.6) を試しています。

次のファイルがあります。

操作.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;
    }
}

その他のさまざまな「操作」クラスは、複数のパッケージにまたがっています。

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

これはなぜですか、どうすれば修正できますか? 私が見つけた最も近いものはIssue 48でしたが、それは2011年5月の時点で修正されたと言います.確かにそれは今ではMavenになっているでしょう...

4

1 に答える 1

2

説明どおりに再現できました。問題は、デフォルトの Reflections コンストラクターが、指定された各パラメーターを見つけることができるディスク上の場所を見つけようとすることにあるようです。IDE で "" を渡すと /bin ディレクトリが検出され、/tmp/so8780228.jar から実行すると /tmp/ が検出されます (ConfigurationBuilder.java:87 のブレークポイント)。

簡単な回避策は、構成ビルドに有用な情報を提供しない "" 以外のものを指定することです。代わりに、正確に 1 つの場所にある "com.company1" のようなものを指定します。

Reflections reflections = new Reflections("com.company1");

この場合、ConfigurationBuilder はスキャンするパス /tmp/so8780228.jar を正しく検出し、すべてが期待どおりに機能します。

別の方法として、ConfigurationBuilder とさらにやり取りして、クラスパス上のすべての jar を検索するように指示することもできます (たとえば、System.getProperty(java.class.path) を反復してそれぞれを追加します) が、パフォーマンスは低下します。

于 2012-07-05T17:49:46.580 に答える