AspectJ & Maven warning: “Advice defined in … has

2019-04-06 15:17发布

问题:

I'm trying to weave some aspects at compile time into a project that becomes a WAR. The aspects advise classes that are within the same project (though in different packages).

I get the warning:

Advice not applied

My aspect is not being executed. Here's my setup:

annotation FooAnnotation.java:

package a;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface FooAnnotation {}

aspect FooAdvice.aj:

package a;
public aspect FooAdvice {
    private static final Log log = LogFactory.getLog(FooAdvice.class);

    Object around() : call( @FooAnnotation * *(..)) {   
        log.info(String.format("Testing around"));
        return proceed();
    }
}

I also tried the annotation:

@Around("call( @FooAnnotation * *(..))")
public Object checkFoo( ProceedingJoinPoint joinPoint) throws Throwable {

As far as I can tell, my pointcut specification is correct, but for some reason the ajc compiler isn't playing ball.

Class FooClass.java:

package b;
@ApplicationPath("/service")
@Path("/{param}")
@Produces("application/json")
@Provider
public class FooClass {

    @POST
    @PUT
    @Path("/{context}/{resource}")
    @FooAnnotation
    public String updateResource(...) {}

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>zzz.group</groupId>
    <artifactId>yyy.artifact</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>yyy.name</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <javaVersion>1.6</javaVersion>
        <org.aspectj-version>1.7.2</org.aspectj-version>
    </properties>

    <dependencies>
        <dependency>
            ... stuff ...
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>${javaVersion}</source>
                    <target>${javaVersion}</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <!--
                    Have to use version 1.2 since version 1.3 does not appear to work
                    with ITDs
                -->
                <version>1.4</version>
                <dependencies>
                    <!--
                        You must use Maven 2.0.9 or above or these are ignored (see
                        MNG-2972)
                    -->
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>${org.aspectj-version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${org.aspectj-version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <!-- <goal>test-compile</goal> -->
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <outxml>true</outxml>
                    <source>${javaVersion}</source>
                    <target>${javaVersion}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

回答1:

Aha! Found the answer here:

aspectj: why advice cannot be applied?

It has nothing to do with maven.

The reason is that in my example, the method is being called from within the jax-rs framework by indirect loading. The call() advice wants to weave the caller, but the ajc compiler can't know where the caller is. The fix is to change the advice to execution() thusly:

Object around() : execution(@FooAnnotation * *(..)) {...}

This differs because it weaves around the execution (which ajc can find), rather than the caller.

Done.