Guice и Размышления внутри Jar File - PullRequest
4 голосов
/ 08 января 2012

Я экспериментирую с Google Guice (3.0) и Google Reflections (0.9.6).

У меня есть следующие файлы:

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

Другие различные классы "операций" распространяются по нескольким пакетам.

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

И, наконец, 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);
    }
}

После выполнения App.java внутри IntelliJ я получаю следующий вывод, как и ожидалось:

Калькулятор: 3 3
Модуль: 0
Деление: 1
Умножение: 9
Сложение: 6

Однако, когда я упаковываю это приложение как банку, я получаю только следующий вывод:

Калькулятор: 3 3

Почему это и как я могу это исправить?Самым близким, что я нашел, был Выпуск 48 , но там написано, что он исправлен по состоянию на май 2011 года. Конечно, сейчас это могло бы попасть в Maven ...

1 Ответ

2 голосов
/ 05 июля 2012

Я смог воспроизвести это точно так, как описано. Проблема заключается в том, что конструктор Reflections по умолчанию пытается найти место на диске, где можно найти каждый заданный параметр. При передаче "" в IDE он находит каталог / bin, а при запуске из /tmp/so8780228.jar находит / tmp / (точка останова в ConfigurationBuilder.java:87)

Простой обходной путь - дать что-то отличное от "", которое не дает сборке конфигурации никакой полезной информации, а вместо этого дать что-то вроде "com.company1", которое можно найти только в одном месте.

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

В этом случае ConfigurationBuilder правильно находит путь /tmp/so8780228.jar для сканирования, и все работает как положено.

В качестве альтернативы, вы можете больше взаимодействовать с ConfigurationBuilder и указывать ему выполнять поиск в каждом jar-адресе на classpath (например, iterate System.getProperty (java.class.path) и добавлять каждый), но производительность пострадает.

...