Подтвердить что ты не робот

Поддерживает ли система Java 9 Module дополнительные зависимости?

Фон

В maven артефакт может объявлять зависимость с помощью

<optional>true</optional>

что означает, что зависимость не требуется, но может быть использована, если присутствует.

Состояние модульной системы, похоже, указывает, что модуль может читать только модули, которые ему необходимы.

Вопросы

  • Система Java 9 действительно не поддерживает дополнительные зависимости?
  • Почему бы и нет?
  • Какие альтернативы факультативным зависимостям предоставляет система модуля Java 9?

Использовать случай

У меня есть структура, которая объединяет различные библиотеки, которые могут или не могут использоваться приложением. В настоящее время эта структура представляет собой единый JAR, который отражает путь к классам для пропуска кода интеграции для отсутствующих библиотек.

Я думаю, мы могли бы разделить это на отдельный модуль для каждой конфигурации, но это вызовет комбинаторный взрыв в количестве JAR, потому что нам потребуется не только отдельный JAR для каждой необязательной зависимости, но и отдельный JAR для большинства пар дополнительных зависимостей...

4b9b3361

Ответ 1

Да, поддерживаются дополнительные зависимости. Цитата из исходное предложение:

Расширьте язык деклараций модуля, чтобы модификатор static использовался в директиве requires со следующими значениями:

  • Во время компиляции requires static M выражает обязательную зависимость. Это ошибка, если подходящий модуль не может быть найден среди наблюдаемых модулей и разрешен.

  • В фазах после времени компиляции requires static M выражает необязательную зависимость. Система модуля не будет искать наблюдаемые модули для подходящего модуля во время разрешения, но если итоговый графа модуля содержит подходящий модуль, он добавит соответствующий край читаемости перед выполнением обычных проверок здравобезопасности после разрешения. [...]

Таким образом, гипотетическое объявление модуля формы

module joda.beans {
    requires static joda.collect;
    ...
}

гарантирует, что модуль joda.collect доступен во время компиляции, поэтому код в модуле joda.beans, который ссылается на joda.collect, может быть скомпилирован без каких-либо проблем. Тем не менее, он не гарантирует, что joda.collect доступен во время соединения или времени выполнения.

(Тем временем для этой функции была создана официальная документация .)

Я написал демо для этого. Интересными примерами являются module-info.java модуля, объявляющие необязательные зависимости...

module org.codefx.demo.advent {
    // list the required modules
    requires org.codefx.demo.advent.calendar;
    // with 'static' the factories are only required at compile time;
    // to be present at run time either other modules most require them
    // or they must be added with the '--add-modules' command line option
    requires static org.codefx.demo.advent.factory.chocolate;
    requires static org.codefx.demo.advent.factory.quote;
}

... и код в том же модуле, который хочет получить доступ к типам из своих необязательных зависимостей. Он должен быть написан так, что он терпит неудачу, если отсутствуют типы ChocolateFactory и/или QuoteFactory:

private static List<SurpriseFactory> createSurpriseFactories() {
    return Stream.of(
            createChocolateFactoryIfAccessible(),
            createQuoteFactoryIfAccessible())
            .flatMap(Optional::stream)
            .collect(toList());
}

private static Optional<SurpriseFactory> createChocolateFactoryIfAccessible() {
    try {
        return Optional.of(new ChocolateFactory());
    } catch (NoClassDefFoundError er) {
        return Optional.empty();
    }
}

private static Optional<SurpriseFactory> createQuoteFactoryIfAccessible() {
    try {
        return Optional.of(new QuoteFactory());
    } catch (NoClassDefFoundError er) {
        return Optional.empty();
    }
}

Наконец, командную строку можно использовать для определения того, какие модули запускаются приложением:

$java \
    --add-modules org.codefx.demo.advent.factory.chocolate,org.codefx.demo.advent.factory.quote \
    -p mods -m org.codefx.demo.advent

Конечно, также возможно, что другие модули требуют их необязательно, что вынуждает JVM включать их в граф модулей.