Gradle + AspectJ日志跟踪尝试在 “instrumentation”期间失败并重新编译项目

2020年9月16日 70点热度 0条评论

编辑:
我在这里将虚拟源代码推送到https://github.com/swapnil-kotwal-sp/basic-demo
它似乎也在编译以及同时执行AspectJ instrumentation
但是,我在instrumentation期间收到警告

[ant:iajc] 
build config error: skipping missing, empty or corrupt aspectpath entry: /Users/swapnil.kotwal/Downloads/basic-demo/my-demo/src/com/my/demo/TracingAspect.java

有人可以帮我解决此
TracingAspect.java问题吗?

我的 Ant 目标如下所示。.我已将其转换为Gradle构建脚本,如下面的
code block所示

<target name="weave-aspects" depends="compile, jar-common" unless="weave.suppressed"
          description="weaves the AspectJ's aspects into classes compiled by compile target">
    <taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
      <classpath>
        <pathelement location="${abcd.proj.base}/lib/aspectj-1.9.4/aspectjtools-1.9.4.jar" />
      </classpath>
    </taskdef>

    <echo message="Weaving the AspectJ's aspects into class files ..." />

    <iajc inpath="${classes}" destdir="${classes}"
          debug="true" fork="true"
          maxmem="${iajc.memoryLimit}"
          source="${javaVersion}">
    <!-- path of jar containing TracingAspect -->
    <aspectpath>
       <path>
         <fileset dir="${pqr.bundle.image}" includes="pqr-bundle-common*.jar" />
       </path>
    </aspectpath>
    <classpath>
       <pathelement path="${deps}" />
       <pathelement path="${abcd.proj.base}/lib/aspectj-1.9.4/aspectjrt-1.9.4.jar" />
      </classpath>
    </iajc>
  </target>

Gradle 转换为


plugins {
        id "io.freefair.aspectj.post-compile-weaving" version "5.1.1"
        //id "aspectj.gradle" version "0.1.6"
        //id "aspectj.AspectjGradlePlugin" version "0.0.3"
    }

configurations {
    ajc
    aspects
    compile {
        extendsFrom aspects
    }
}

ext {
    aspectjVersion = '1.9.2'
}

dependencies {
    implementation gradleApi() // for custom gradle task/pugin development

    compile project('my-project')
    compile project('my-project1')
    compile project('my-project2')
    // ...

    ajc "org.aspectj:aspectjtools:$aspectjVersion"
    compile "org.aspectj:aspectjrt:$aspectjVersion"
    compile "org.aspectj:aspectjweaver:$aspectjVersion"
    aspects project('my-project1')
    // ...
}


compileJava {
    dependsOn configurations.ajc.getTaskDependencyFromProjectDependency(true, "compileJava")

    doLast{
        System.out.println("Java Version: " + JavaVersion.current());
        ant.taskdef( resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath)

        ant.iajc(
                maxmem: "1024m", fork: "true", Xlint: "ignore",
                destDir: sourceSets.main.output.classesDirs.asPath,
                //my-common.jar consist of my own AspectTracing.class
                aspectPath: "$projectDir/image/pqr-bundle-common*.jar",
                //aspectPath: configurations.aspects.asPath,
                sourceRootCopyFilter: "**/*.java",
                classpath: configurations.compile.asPath,
                source: project.sourceCompatibility,
                target: project.targetCompatibility
        ){
            sourceroots{
                sourceSets.main.java.srcDirs.each{
                    //ignoring root project and adding only sub-modules
                    if(!it.absolutePath.contains("/src/main/java")) {
                        pathelement(location: it.absolutePath)
                    }
                }
            }
        }
    }
}

TracingAspect.java看起来像这样。此类是
aspectpath jar的一部分

    <aspectpath>
       <path>
         <fileset dir="${pqr.bundle.image}" includes="pqr-bundle-common*.jar" />
       </path>
    </aspectpath>
/*
 * The pertypewithin causes all classes that don't have the Untraced annotation
 * to be woven. The pointcuts further limit the use of the tracing loggers to
 * avoid infinite recursion, etc...
 */
@Aspect("pertypewithin(!is(InterfaceType) && !is(EnumType) && (!@my.common.logging.Untraced "
        + "(my-somepackaje..* || my-anotherpackage..*)))")
@Untraced
public class TracingAspect {

    private MyLogger myLogger;
    private static final String ENTERING_PREFIX = "Entering {0}";
    private static final String EXITING_PREFIX = "Exiting {0}";
    private static final String ARGUMENTS = ": Arguments =>";
    private static final String ARGUMENTS_NOT_AVAILABLE = ARGUMENTS + " N/A";
    private static final String RETURN = ", Returns =>";
    private static final String RETURN_NOT_AVAILABLE = RETURN + " N/A";
    private static final String THROWING = "Throwing {0}";

    @Pointcut("staticinitialization(*)")
    public void staticInit() {
    }

    /**
     * This is run in a static initializer block for every woven class, and is
     * used to initialize the trace logger for the class.
     */
    @After("staticInit()")
    public void initLogger(JoinPoint.StaticPart jps) {
        myLogger = MyLogger.getLogger(jps.getSignature().getDeclaringTypeName());
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Pointcuts
    //
    ////////////////////////////////////////////////////////////////////////////

    @Pointcut("execution(new(..))")
    void tracedConstructors() {
    }

    // The !execution(String toString()) avoids infinite recursion by not
    // tracing toString() methods.
    // Also, don't trace the compile-time inserted 'access$nnn' methods. That
    // might (in very specific cases) lead to recursion but more generally just
    // confusing.
    @Pointcut("execution(* *(..)) && !execution(String toString()) && !execution(* access$*(..)) "
            + "&& !@annotation(my.common.logging.Untraced)")
    void tracedMethods() {
    }

    // Advice starts below.

    @Before("tracedConstructors()")
    public void traceConstructorEntry(JoinPoint thisJoinPoint) {
        if (null != myLogger)
            myLogger.trace(() -> entering(thisJoinPoint.getSignature().getName(), thisJoinPoint.getArgs()));
    }

    @AfterReturning("tracedConstructors()")
    public void traceConstructorExit(JoinPoint thisJoinPoint) {
        if (null != myLogger)
            myLogger.trace(() -> exiting(thisJoinPoint.getSignature().getName(), thisJoinPoint.getArgs(), null));
    }

    @AfterThrowing(pointcut = "tracedConstructors()", throwing = "t")
    public void traceConstructorThrow(JoinPoint thisJoinPoint, Throwable t) {
        if (null != myLogger)
            myLogger.trace(() -> MessageFormat.format(THROWING, thisJoinPoint.getSignature().getName()) + " - "
                    + t.toString());
    }

    @Before("tracedMethods()")
    public void traceMethodEntry(JoinPoint thisJoinPoint) {
        if (null != myLogger)
            myLogger.trace(() -> entering(thisJoinPoint.getSignature().getName(), thisJoinPoint.getArgs()));
    }

    @AfterReturning(pointcut = "tracedMethods()", returning = "r")
    public void traceMethodExit(JoinPoint thisJoinPoint, Object r) {
        // Add sensitive return value to log context
        if (((MethodSignature) thisJoinPoint.getSignature()).getMethod()
                .getAnnotation(SensitiveTraceReturn.class) != null) {
            LogContext.addSensitiveValue(r);
        }
        if (null != myLogger){
            myLogger.trace(() -> exiting(thisJoinPoint.getSignature().getName(), thisJoinPoint.getArgs(), r));
        }
    }

    @AfterThrowing(pointcut = "tracedMethods()", throwing = "t")
    public void traceMethodThrow(JoinPoint thisJoinPoint, Throwable t) {
        if (null != myLogger)
            myLogger.trace(() -> MessageFormat.format(THROWING, thisJoinPoint.getSignature().getName()) + " - "
                    + t.toString());
    }

    // End of Advice

    /**
     * Creates entering message trace statement
     *
     * @param method
     *            method name of the log entry
     * @param args
     *            {@code Object} array representing the message parameters
     */
    private String entering(String method, Object[] args) {
        StringBuffer msgBuffer = new StringBuffer(ENTERING_PREFIX);
        Object[] temp = { method };

        if (args != null && args.length > 0) {
            int index = 1;
            msgBuffer.append(ARGUMENTS);
            for (Object arg : args) {
                if (index > 1) {
                    msgBuffer.append(",");
                }
                msgBuffer.append(" {").append(index).append("}");
                index++;
            }
            temp = ArrayUtils.addAll(temp, args);
        } else {
            msgBuffer.append(ARGUMENTS_NOT_AVAILABLE);
        }

        return MessageFormat.format(msgBuffer.toString(), temp);
    }

    /**
     * Creates exiting message trace statement
     *
     * @param method
     *            method name of the log entry
     * @param args
     *            {@code Object} array representing the message parameters
     * @param returnValue
     *            return value from the method, if any
     */
    private String exiting(String method, Object[] args, Object returnValue) {
        StringBuffer msgBuffer = new StringBuffer(EXITING_PREFIX);
        Object[] temp = { method };

        int index = 1;
        if (args != null && args.length > 0) {
            msgBuffer.append(ARGUMENTS);
            for (Object arg : args) {
                if (index > 1) {
                    msgBuffer.append(",");
                }
                msgBuffer.append(" {").append(index).append("}");
                index++;
            }
            temp = ArrayUtils.addAll(temp, args);
        } else {
            msgBuffer.append(ARGUMENTS_NOT_AVAILABLE);
        }

        if (null != returnValue) {
            msgBuffer.append(RETURN).append(" {").append(index).append("}");
            temp = ArrayUtils.addAll(temp, new Object[] { returnValue });
        } else {
            msgBuffer.append(RETURN_NOT_AVAILABLE);
        }
        temp = ArrayUtils.addAll(temp, args);

        return MessageFormat.format(msgBuffer.toString(), temp);
    }
}

interface :- my.common.logging.Untraced仅是空的(现在)

public @interface Untraced {
}

但是,它在
instrumentation期间由于随机编译错误而失败。

(注意:如果没有我的AspectJ编译,则jar创建会正确进行。)

通常,AspectJ应该进行日志跟踪编织,但是它试图再次对其进行编译,因此失败。任何线索,我在这里想念什么?

失败的Java代码如下所示:

private static void runRule(boolean before) {
    String str = (before) ? "before" : "after" ;
}

错误是:

[error] Syntax error, insert "|| Expression" to complete Expression
[ant:iajc] String str = (before) ? "before" : "after" ;
[ant:iajc]               

解决方案如下:

我在这里推送了工作示例演示代码https://github.com/swapnil-kotwal-sp/basic-demo
我还可以在instrumentation期间解决我的业务项目问题,问题出在下面的代码中。

private static void runRule(boolean before) {
    String str = (before) ? "before" : "after" ;
}

基本上,AspectJ不喜欢
boolean before周围的圆括号,我更改了代码,AspectJ开始正常工作。

private static void runRule(boolean before) {
    String str = before ? "before" : "after" ;
}