Посткомпиляция аспектов ткачества в проект с использованием Gradle - PullRequest
3 голосов
/ 04 октября 2019

Фон

Выполнение проектов после компиляции с использованием:

  • AspectJ 1.9.4
  • io.freefair.aspectj.post-compile-weaving 4.1.1
  • Java 11.0.3
  • Gradle 5.6.2 (Groovy 2.5.4, Kotlin 1.3.41)

Этот проект не использует Maven или Spring.

Макет

Проекты включают в себя:

  • app.aspects - Содержит один класс LogAspect с комментариями @Aspect.
  • app.aspects.weaver - Нет исходных файлов, только зависимости для объявления аспектов и проекта для плетения.
  • app.common - Определяет @Log аннотацию, на которую ссылаются pointcuts, описанные в LogAspect.
  • app.program.main - Файлы, которые должны быть сотканы с точками соединения, описанными в LogAspect.

Gradle

Здесь определяются файлы сборки, которые относятся к аспектам. Идея заключается в том, что плетение не зависит от приложения, поэтому о классах плетения не нужно знать ни общих классов приложения, ни основной программы. Скорее, основной программе нужна только ссылка @Log из общего пакета, а AJC позаботится о переплетении.

app.aspects

apply plugin: "io.freefair.aspectj.post-compile-weaving"

dependencies {
    // For the @Log annotation
    compileOnly project(':app.common')

    // The LogAspect's joinpoint references the Main Program
    compileOnly project(':app.program.main')

    // Logging dependency is also compiled, but not shown here
}

app.aspects.weaver

apply plugin: "io.freefair.aspectj.post-compile-weaving"

dependencies {
    compileOnly "org.aspectj:aspectjrt:1.9.4"

    // This should set the -aspectpath ?
    aspect project(":app.aspects")

    // This should set the -inpath ?
    inpath(project(":app.program.main")) {
        // Only weave within the project
        transitive = false
    }
}

Классы

Журнал

Аннотация Log проста:

package com.app.common.aspects;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.CONSTRUCTOR })
public @interface Log {
    boolean secure() default false;
}

Основная программа

Основная программа похожа на:

package com.app.program.main;

import com.app.common.aspects.Log;

@Log
public class Program {

  /** This is the method to weave. */
  protected void run() throws InterruptedException, TimeoutException {
  }
}

Аспект ведения журнала

Аспект ведения журнала напоминает (см. Код из вопроса ):

@Aspect
public class LogAspect {

    // In the future this will target points annotated with @Log
    @Pointcut("execution(* com.app.program.main.Program.run(..))")
    public void loggedClass() {
    }

    @Around("loggedClass()")
    public Object log(final ProceedingJoinPoint joinPoint) throws Throwable {
      return log(joinPoint, false);
    }

    private Object log(final ProceedingJoinPoint joinPoint, boolean secure) throws Throwable {
      // See last year's code for the full listing
      log.info("\u21B7| {}{}#{}({})", indent, className, memberName, params);
    }
}

Проблема

Похоже, ткачество происходит, но совет не может быть найден:

... / app.aspects / build / classes / java / main! Com / app / aspect / LogAspect. класс [warning] advice, определенный в com.app.aspects.LogAspect, не был применен [Xlint: adviceDidNotMatch]

Вопрос

Что необходимо изменить, чтобы переплетение LogAspect в Program метод run() работает с использованием Gradle?

Файл опций

Файл ajc.options показывает:

-inpath
.../app.aspects/build/classes/java/main
-classpath
.../.gradle/caches/modules-2/files-2.1/org.aspectj/...
-d
.../app.aspects/build/classes/java/main
-target
11
-source
11

Это дискубедившись, что -aspectpath не отображается и -inpath выводит app.aspects вместо app.program.main.

1 Ответ

1 голос
/ 15 октября 2019

Слияние apps.aspects и apps.aspects.weaver в одном проекте привело к:

Точка соединения 'метод-выполнение (void com.app.program.main.Program.run ())'в типе 'com.app.program.main.Program' (Program.java:396), советуемом по совету из 'com.app.aspects.LogAspect' (LogAspect.class (из LogAspect.java))

Хотя это решает проблему, я не понимаю, почему LogAspect должен быть в том же проекте, который выполняет плетение. Файл Gradle становится:

apply plugin: "io.freefair.aspectj.post-compile-weaving"

dependencies {
    compileOnly "org.aspectj:aspectjrt:1.9.4"
    compileOnly project(':app.common')
    compileOnly project(':app.program.main')

    compileOnly org_apache_logging_log4j__log4j_api

    inpath(project(":app.program.main")) {
        transitive = false
    }
}

compileJava.ajc.options.compilerArgs += "-showWeaveInfo"
compileJava.ajc.options.compilerArgs += "-verbose"
...