Ограничение транзитивной зависимости от области выполнения в Maven

У меня есть 2 проекта с использованием Maven. Первый - это библиотека, содержащая классы и методы утилиты. Второй проект - это фактическое приложение, имеющее библиотеку в качестве зависимости. Моя библиотека использует внутреннюю стороннюю библиотеку.

Итак, это зависимости:

  • Моя библиотека: зависит от сторонней библиотеки
  • Мое приложение: зависит от моей библиотеки

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

Если область для всех моих зависимостей была компилировать, она не достигла бы моей цели. Есть ли способ достичь этого в Maven 3?

Ответ 1

Очень хороший вопрос, и, к сожалению, вы не можете сделать это, используя Maven 3, или 2, или любую другую версию, из-за ее фундаментального дизайна. То, о чем вы спрашиваете, на самом деле является желаемым и идеальным поведением, поскольку фактически любые артефактные зависимости compile должны быть транзитивными с областью действия runtime. Однако подобный дизайн приводит к некоторым проблемам. Как вы можете прочитать в Введение в механизм зависимости Maven о области действия compile:

Предполагается, что [транзитивные зависимости зависимости компиляции, которые сами являются зависимостями компиляции, следует учитывать] область выполнения вместо этого, чтобы все зависимости компиляции должны быть явно перечислены - однако, есть случай, когда библиотека, от которой вы зависите, расширяет класс из другого библиотека, заставляя вас быть доступными во время компиляции. За это причина, зависимости времени компиляции остаются как область компиляции, даже когда они переходные.

Итак, как вы видите, на самом деле вам нужен правильный дизайн этого поведения, который, к сожалению, невозможно реализовать.

Ответ 2

За последние три года ничего не изменилось, поэтому ответ Михала по-прежнему прав: нет способа ограничить транзитивную видимость в Maven.

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

Ответ 3

В вашем приложении вы можете объявить явную зависимость от сторонней библиотеки, используя область выполнения.

Это предотвращает просмотр сторонней библиотеки во время компиляции и, следовательно, никакие прямые действия не могут проникнуть внутрь. Однако он все равно будет присутствовать во время выполнения (поскольку он необходим вашей библиотеке).

Это работает, но неудобно и заслуживает объяснительного комментария XML в pom.

Ответ 4

Другие ответы верны. Помимо работы с отсутствующей ключевой функцией в maven путем разделения искусственного API-модуля, у вас также есть следующие альтернативы:

  • исключить транзитивные зависимости, а затем напрямую зависеть от них (вам нужно самостоятельно управлять номерами версий)
  • Использовать контроль импорта checkstyle и CI. Таким образом, члены команды могут использовать транзиты, но затем проверка maven завершится неудачно.
  • Используйте gradle. Это решение многих ограничений Maven

Ответ 6

Кажется, что работает, используйте раздел <dependencyManagement> в pom. Вы захотите проверить наличие каких-либо побочных эффектов, так как он работает в рамках всего проекта. И вы должны указать каждую библиотеку отдельно.

Следующий пример кода позволил мне принудительно заставить guava (который был задуман в проекте google guice как транзитивная зависимость во время компиляции) везде во время выполнения.

<dependencyManagement> <dependencies> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <scope>runtime</scope> </dependency> </dependencies> </dependencyManagement>