«1. Обзор

В многомодульном проекте Maven эффективный POM является результатом слияния всех конфигураций, определенных в модуле и его родительских элементах.

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

В этом уроке мы узнаем, как переопределить конфигурацию родительского плагина.

2. Наследование конфигурации по умолчанию

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

Для этого Maven объединяет файлы XML на уровне элементов. Если дочерний элемент определяет элемент с другим значением, он заменяет элемент родительского элемента. Давайте посмотрим на это в действии.

2.1. Структура проекта

Во-первых, давайте определим многомодульный проект Maven для экспериментов. Наш проект будет состоять из одного родителя и двух дочерних элементов:

+ parent
     + child-a
     + child-b

Допустим, мы хотим настроить подключаемый модуль maven-compiler для использования разных версий Java между модулями. Давайте настроим наш проект для использования Java 11 в целом, но дочерний элемент будет использовать Java 8.

Мы начнем с родительской конфигурации:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>11</source>
        <target>11</target>
        <maxmem>512m</maxmem>
    </configuration>
</plugin>

Здесь мы указали дополнительное свойство, maxmem, которое мы также хотим использовать. Однако мы хотим, чтобы у child-a были собственные настройки компилятора.

Итак, давайте настроим child-a для использования Java 8:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
    </configuration>
</plugin>

Теперь, когда у нас есть наш пример, давайте посмотрим, что он делает с эффективным POM.

2.2. Понимание эффективного POM

Эффективный POM зависит от различных факторов, таких как наследование, профили, внешние настройки и т. д. Чтобы увидеть фактический POM, давайте запустим mvn help: Effective-pom из каталога child-a:

mvn help:effective-pom

...
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <maxmem>512m</maxmem>
    </configuration>
</plugin>

Как и ожидалось, child-a имеет свои собственные варианты исходных и целевых значений. Однако еще одним сюрпризом является то, что он также имеет свойство maxmem от своего родителя.

Это означает, что если определено какое-либо дочернее свойство, оно будет иметь преимущество, в противном случае будет использоваться родительское.

3. Расширенное наследование конфигурации

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

3.1. Работа со списками

В предыдущем примере мы видели, что происходит, если дочерний элемент имеет другое значение. Теперь рассмотрим случай, когда у потомка другой список элементов. В качестве примера рассмотрим включение нескольких каталогов ресурсов с помощью плагина maven-resources-plugin.

В качестве основы давайте настроим родительский модуль для включения ресурсов из каталога parent-resources:

<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <configuration>
        <resources>
            <resource>
                <directory>parent-resources</directory>
            </resource>
        </resources>
    </configuration>
</plugin>

На этом этапе child-a унаследует эту конфигурацию плагина от своего родителя. Однако предположим, что мы хотим определить альтернативный каталог ресурсов для дочернего элемента:

<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <configuration>
        <resources>
            <resource>
                <directory>child-a-resources</directory>
            </resource>
        </resources>
    </configuration>
</plugin>

Теперь давайте рассмотрим действующий POM:

mvn help:effective-pom
...
<configuration>
    <resources>
        <resource>
            <directory>child-a-resources</directory>
        </resource>
    </resources>
</configuration>

В этом случае весь список переопределяется дочерней конфигурацией. .

3.2. Append Parent Configuration

Возможно, мы хотим, чтобы некоторые дочерние элементы использовали общий каталог ресурсов, а также определяли дополнительные. Для этого мы можем добавить родительскую конфигурацию, используя combo.children=†append“ для элемента ресурсов в родительском элементе:

<resources combine.children="append">
    <resource>
        <directory>parent-resources</directory>
    </resource>
</resources>

Следовательно, действующий POM будет содержать оба из них:

mvn help:effective-pom
....
<resources combine.children="append">
    <resource>
        <directory>parent-resources</directory>
    </resource>
    <resource>
        <directory>child-a-resources</directory>
    </resource>
</resources>

Атрибуты объединения не распространяются ни на какие вложенные элементы. Таким образом, если бы раздел ресурсов имел сложную структуру, вложенные элементы были бы объединены с использованием стратегии по умолчанию.

3.3. Переопределить дочернюю конфигурацию

В предыдущем примере дочерний элемент не полностью контролировал окончательный POM из-за родительской стратегии объединения. Дочерний элемент может переопределить родительский, добавив в свой элемент resources, comb.self=“override”:

<resources combine.self="override">
    <resource>
        <directory>child-a-resources</directory>
    </resource>
</resources>

В этом случае дочерний элемент восстанавливает контроль:

mvn help:effective-pom
...
<resources combine.self="override">
    <resource>
        <directory>child-a-resources</directory>
    </resource>
</resources>

4. Ненаследуемые плагины ~~ ~»

«Предыдущие атрибуты подходят для тонкой настройки, но они не подходят, когда дочерний элемент полностью не согласен со своим родителем.

Чтобы избежать наследования плагина вообще, мы можем добавить свойство \u003cinherited\u003efalse\u003c/inherited\u003e на родительском уровне:

<plugin>
    <inherited>false</inherited>
    <groupId>org.apache.maven.plugins</groupId>
    ...
</plugin>

Это означает, что плагин будет применен только к родительскому и не будет распространяться на его потомков.

5. Заключение

В этой статье мы увидели, как переопределить конфигурацию родительского плагина.

Сначала мы изучили поведение по умолчанию. Затем мы увидели, как родитель может определить политику слияния и как потомок может ее отклонить. Наконец, мы увидели, как пометить плагин как ненаследуемый, чтобы избежать его переопределения всеми дочерними элементами.

Как всегда, код доступен на GitHub.