Как использовать AspectJ Maven для двоичного переплетения после фазы Javac + Lombok

У меня есть проект, который использует скомпилированные аспекты и переплетает их во время компиляции. Я хочу добавить Lombok, но, к сожалению, Lombok не поддерживает AJC. Поскольку у этого проекта нет собственных источников аспектов, я настроил плагин AspectJ Maven для выполнения посткомпиляционного переплетения после компиляции с помощью Javac + Lombok.

Вот конфигурация плагина AspectJ Maven:

<forceAjcCompile>true</forceAjcCompile>
<sources/>
<weaveDirectory>${project.build.outputDirectory}</weaveDirectory>

Он прикрепляется к фазе компиляции сразу после компиляции плагина Maven Compiler. Таким образом, сначала будет вызываться Lombok + Javac, а позже AJC выполнит переплетение с файлами классов, сгенерированных Javac.

Есть ли какие-либо ограничения / недостатки при выполнении переплетения байт-кода для классов, сгенерированных javac?

Может быть, есть лучший способ заставить Maven + Lombok + Aspects + Idea работать вместе без проблем.

Вот минимальный пример проекта: https://github.com/Psimage/aspectj-and-lombok


person Yaroslav Buhaiev    schedule 11.07.2019    source источник


Ответы (1)


Когда вы задали мне другой вопрос в комментарии, я действительно подумал, что у вас проблемы с вашим подходом, но он работает. Единственное, что мне нужно было сделать, чтобы запустить тест непосредственно из IDE (IntelliJ IDEA), - это фактически делегировать приложение и исполнителей тестов в Maven, потому что в противном случае IDEA не применяет Lombok + AspectJ одновременно.

Делегировать действия по сборке / запуску IDE в Maven

Если ваш подход работает, используйте его. Но на самом деле AspectJ Maven предлагает другой подход: сначала компилировать с помощью компилятора Maven. в другой выходной каталог, затем используйте этот каталог как каталог для плетения для компилятора AspectJ. Тем не менее, образец POM не работает на 100%, потому что при указании выходного каталога для Javac в командной строке этот каталог должен существовать, он не будет создан компилятором. Так что вам тоже понадобится некрасивый экшен Antrun:

<plugins>

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.8</version>
    <executions>
      <execution>
        <id>unwovenClassesFolder</id>
        <phase>generate-resources</phase>
        <configuration>
          <tasks>
            <delete dir="${project.build.directory}/unwoven-classes"/>
            <mkdir dir="${project.build.directory}/unwoven-classes"/>
          </tasks>
        </configuration>
        <goals>
          <goal>run</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <executions>
      <execution>
        <!-- Modifying output directory of default compile because non-weaved classes must be stored
             in separate folder to not confuse ajc by reweaving already woven classes (which leads to
             to ajc error message like "bad weaverState.Kind: -115") -->
        <id>default-compile</id>
        <configuration>
          <compilerArgs>
            <arg>-d</arg>
            <arg>${project.build.directory}/unwoven-classes</arg>
          </compilerArgs>
        </configuration>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <configuration>
      <aspectLibraries>
        <aspectLibrary>
          <groupId>me.yarosbug</groupId>
          <artifactId>aspects</artifactId>
        </aspectLibrary>
      </aspectLibraries>

      <forceAjcCompile>true</forceAjcCompile>
      <sources/>
      <weaveDirectories>
        <weaveDirectory>${project.build.directory}/unwoven-classes</weaveDirectory>
      </weaveDirectories>
    </configuration>
    <executions>
      <execution>
        <phase>process-classes</phase>
        <goals>
          <goal>compile</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
  </plugin>

</plugins>

Я бы предложил другой подход в качестве альтернативы:

  1. Создайте нетканый Java-модуль, делая там вещи Java + Lombok.
  2. Создайте отдельный модуль для двоичного плетения AspectJ, используя модуль Java в качестве зависимости плетения. Поскольку ваш модульный тест зависит как от Lombok, так и от AspectJ, поместите тест в этот модуль.

Преимущество состоит в том, что вам не нужно возиться с несколькими компиляторами, фазами выполнения, каталогами вывода, Antrun и т. Д.


Обновление:

Я клонировал ваш MCVE на GitHub и эта фиксация в ветке master отражает то, что я объяснил в моем примере XML выше.

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

Multi-phase compilation: 1. Java + Lombok, 2. AspectJ binary weaving

There are many changes (sorry, I should have split them into multiple
commits):
  - Marker annotation renamed to @marker and moved to separate module
    because the main application should not depend on the aspect module.
    Rather both application and aspect now depend on a common module.
  - New module "main-app-aspectj" does only AspectJ binary weaving on
    the already lomboked Java application.
  - Both application modules have slightly different unit tests now: One
    checks that Lombok has been applied and AspectJ has not, the other
    checks that both have been applied.
  - Aspect pointcut limits matching to "execution(* *(..))" in order to
    avoid also matching "call()" joinpoints.

The end result is that now we have a clear separation of concerns, clear
dependencies, no more scripted Ant build components and the new option
to use the lomboked code optionally with or without aspects applied
because both types or JARs are created during the build.

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

person kriegaex    schedule 12.07.2019
comment
Обратите внимание, что я добавил в свой ответ дополнительную информацию и ресурсы. - person kriegaex; 12.07.2019
comment
Что я сделал, чтобы IDEA запустила мой проект, так это убедиться, что Delegate to javac установлен в Java compiler настройках, а в фасете аспектаj для модуля основного приложения включена опция post-compile weave mode (она не сбрасывается при повторном импорте проекта maven). Спасибо, что сообщили мне о возможности делегирования в maven. Никогда об этом не знал. - person Yaroslav Buhaiev; 12.07.2019
comment
Я посмотрел на официальный подход, который вы связали, но при компиляции нет проблем с ajc, поэтому я не менял каталог. И привязка к классам процессов кажется ненужной. - person Yaroslav Buhaiev; 12.07.2019
comment
Спасибо за возможность поиграть с этим образцом проекта. К сожалению, я не могу использовать ваш подход многофазной компиляции в реальном приложении. Я хочу добавить Lombok в старый проект, в котором много чего происходит, но добавление Lombok изменит результирующий байт-код (изменение ajc на javac + binary ajc). Есть ли риски при переходе на посткомпиляционное ткачество времени? - person Yaroslav Buhaiev; 12.07.2019
comment
Вопрос очень общий. Какие риски и по сравнению с чем? Ничего подобного, что могло бы помешать мне его использовать. Кроме того, то, что вы только что сказали мне об устаревшем приложении, не похоже на то, что мой двухэтапный подход не сработает. Кстати, если вы хотите скомпилировать Java-код с помощью Ajc напрямую, подумайте об использовании Сначала деломбок через плагин Maven, а затем компилируйте в обычном режиме. - person kriegaex; 13.07.2019
comment
Я предположил, что изменение байт-кода из javac может привести к ошибкам, которых нет при компиляции и переплетении одновременно с ajc. Я посмотрел на подход Деломбока, но официальное использование требует перемещения классов ломбока в src / main / lombok, что недопустимо. В общем, у меня были проблемы с тем, чтобы аспекты IDEA + delombok + работали в унисон. - person Yaroslav Buhaiev; 13.07.2019
comment
Есть люди, которые находят решение для каждой проблемы, и другие, которые находят проблему в каждом решении. В FAQ по плагинам рассказывается, как переопределить исходную папку. В любом случае, каким бы негибким и нежелательным вы ни были, я внес много предложений сейчас, может быть, мы просто закроем обсуждение. Удачи тебе. - person kriegaex; 16.07.2019
comment
Спасибо за потраченное время @kriegaex. Я заставил работать как решения после компиляции, так и решения delombok, но выбрал первое. Тебе тоже удачи. - person Yaroslav Buhaiev; 17.07.2019
comment
Я только что вернулся из недельной поездки, и мне было любопытно попробовать Delegate to javac plus post compile weave mode в моих настройках IDEA. Это не работает в моем проекте с двумя прикладными модулями (нетканым, затем тканым). Тест aspectsApplied не проходит. Мне пришлось вернуться к делегированию Maven, как я предложил в своем ответе. - person kriegaex; 19.07.2019
comment
Добро пожаловать назад! Проблема с вашей настройкой заключается в том, что IDEA не поддерживает параметр ‹weaveDependencies› - person Yaroslav Buhaiev; 20.07.2019
comment
Да, у IDEA есть много недостатков, связанных с AspectJ, и открытых заявок. Много лет назад был начальный всплеск поддержки AJ, но с тех пор он так и не был улучшен или закончен, поэтому моя деятельность по разработке является своего рода шизофренией: я использую IDEA 90%, за исключением всего, что связано с AspectJ. По-прежнему предпочитают Eclipse из-за его более зрелой поддержки AJ, хотя и не идеальной. Я просто использовал IDEA в этом случае, потому что вы это сделали. - person kriegaex; 20.07.2019
comment
Я попытался настроить IDEA для своего случая просто из любопытства. Я был удивлен, что это сработало :) - person Yaroslav Buhaiev; 20.07.2019
comment
По-видимому, это все еще не сработает для Java 11, потому что плагин не может с этим справиться. См. github.com/mojohaus/aspectj-maven-plugin/pull / для возможной замены - person Jakub Bochenski; 24.02.2020
comment
Якуб, ваш комментарий не имеет отношения к этому вопросу. В любом случае, для Java ›8 вы действительно можете использовать плагин fork com.nickwongdev: aspectj-maven-plugin в качестве замены. Даже готовящаяся к выпуску IntelliJ IDEA 2020.x распознает это. Таким образом, даже несмотря на то, что существует не очень хорошо поддерживаемый плагин Mojohaus (сопровождающий слишком занят работой и личными вещами, он сказал мне), есть решение проблемы. Спасибо, что упомянули об этом. Мы также работаем над внесением необходимых изменений в исходную версию. - person kriegaex; 25.02.2020