Модульность Java с внедрением зависимостей - PullRequest
0 голосов
/ 06 ноября 2019

Предположим, что приложение основано на OpenJDK 11 + OpenJFX 11 . Кодовая база организована в одном Java-модуле (см. Руководство по модульности Java 9 для справки).

До сих пор я совмещал все свои проекты на основе JavaFX с Googleрамки внедрения зависимостей Guice . Для модульных проектов это не работает ...

SQLiteCompassApplication.java

public class SQLiteCompassApplication extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    public void start(Stage stage) throws Exception {

         Injector injector = Guice.createInjector(new MyModule());

         FXMLLoader fxmlLoader = injector.getInstance(FXMLLoader.class);

         try(InputStream fxmlStream = getClass().getResourceAsStream("/view/View.fxml")) {

            Parent root = fxmlLoader.load(fxmlStream);
            stage.setScene(new Scene(root));
            stage.setTitle("SQLite Compass");
            stage.setOnCloseRequest(event -> System.exit(0));
            stage.show();
        }
    }
}

module-info.java

module org.x1c1b.sqlitecompass {

    requires javafx.controls;
    requires javafx.fxml;
    requires com.google.guice;

    exports org.x1c1b.sqlitecompass;
}

Для простоты конфигурация Guice , что означает объявленные модули Guice ( не для смешения с java-модулями), isnвставлен, но все еще работает для немодульных проектов.

При выполнении этого кода я получаю следующее исключение:

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field com.google.inject.Injector org.x1c1b.sqlitecompass.config.provider.FXMLLoaderProvider.injector accessible: module org.x1c1b.sqlitecompass does not "opens org.x1c1b.sqlitecompass.config.provider" to module com.google.guice
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:340)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:280)
    at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:176)
    at java.base/java.lang.reflect.Field.setAccessible(Field.java:170)
    at com.google.guice@4.2.2/com.google.inject.internal.SingleFieldInjector.<init>(SingleFieldInjector.java:38)
    at com.google.guice@4.2.2/com.google.inject.internal.MembersInjectorStore.getInjectors(MembersInjectorStore.java:126)
    at com.google.guice@4.2.2/com.google.inject.internal.MembersInjectorStore.createWithListeners(MembersInjectorStore.java:93)
    at com.google.guice@4.2.2/com.google.inject.internal.MembersInjectorStore.access$000(MembersInjectorStore.java:36)
    at com.google.guice@4.2.2/com.google.inject.internal.MembersInjectorStore$1.create(MembersInjectorStore.java:45)
    at com.google.guice@4.2.2/com.google.inject.internal.MembersInjectorStore$1.create(MembersInjectorStore.java:41)
    at com.google.guice@4.2.2/com.google.inject.internal.FailableCache$1.load(FailableCache.java:40)
    at com.google.common@25.1-android/com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3444)
    at com.google.common@25.1-android/com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2193)
    at com.google.common@25.1-android/com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2152)
    at com.google.common@25.1-android/com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2042)
    ... 39 more
Exception running application org.x1c1b.sqlitecompass.SQLiteCompassApplication

Я мог бы исправить эту проблему, вставив opens org.x1c1b.sqlitecompass.config.provider; в module-info.java. Но это приводит к дальнейшим исключениям ...

Как мне настроить мой модуль / module-info.java для его использования с Google Guice в целом? Можно ли использовать Google Guice и Модульность в комбинации?

EDIT

Кажется, работает, когда я изменяюследующие строки:

  • Добавить exports org.x1c1b.sqlitecompass.config, где объявлены мои Guice модули, к module-info.java
  • Выполнить программу с дополнительной опцией VM --add-opens java.base/java.lang=com.google.guice

Но я бы предположил, что найден более обходной путь здесь , чем официальное решение ...

1 Ответ

1 голос
/ 06 ноября 2019

Вы должны открыть все свои пакеты, которые будут доступны через отражение Guice. Самый простой способ сделать это - просто объявить весь модуль как open, поместив это слово перед module в вашем module-info.java.

...