Home > database >  AspectJ not working with compile time weaving
AspectJ not working with compile time weaving

Time:12-19

I'm trying to do a SQL query profiling using AOP

Below is my snippet from @Aspect defenition

@Pointcut("(call(* org.springframework.jdbc.core.JdbcTemplate.query*(..)) || call(* org.springframework.jdbc.core.JdbcTemplate.update*(..)))")
public void profileQuery() {
}

@Around("profileQuery()")
public Object profile(ProceedingJoinPoint thisJoinPoint) throws Throwable {
    logger.info("profileQuery() aspect Before");
    Object pjp= thisJoinPoint.proceed();
    logger.info("profileQuery() aspect After");
    return pjp;
}

POM snippet for aspectj maven plugin

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.14.0</version>
    <configuration>
        <complianceLevel>${java.version}</complianceLevel>
        <showWeaveInfo>true</showWeaveInfo>
        <verbose>true</verbose>
        <Xlint>ignore</Xlint>
        <encoding>UTF-8 </encoding>
    </configuration>
    <dependencies>
    </dependencies> 
    <executions>
        <execution>
            <id>compile</id>
            <phase>process-classes</phase>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>    
        </execution>
    </executions>
</plugin>

POM snippet for maven compiler plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <fork>true</fork>
        <source>${java.version}</source>
        <target>${java.version}</target>
        <useIncrementalCompilation>false</useIncrementalCompilation>
        <excludes>
          <exclude>**/*.*</exclude>
        </excludes>
    </configuration>
</plugin>

I tried using Eclipse and also tried compiling outside Eclipse Command used mvn clean install -Dmaven.test.skip=true

No issues in building and deploying it on Tomcat 8.5.83 , also the APIs are working, but the aspect is not being intercepted as expected.

CodePudding user response:

There are several problems in your POM and code, which I fixed in this pull request, for example:

  • You configured AspectJ Maven Plugin in the pluginManagement section, but forgot to actually add the plugin to the project in a separate plugins section.

  • Your example does not contain a test base directory. Therefore, you need to remove goal test-compile in order to avoid build errors.

  • When using org.codehaus.mojo:aspectj-maven-plugin, using complianceLevel is not enough, you also need to specify source and target. Or you simply switch to the better dev.aspectj:aspectj-maven-plugin variant, then complianceLevel is enough.

  • Package name aspect is not OK for native AspectJ, because in AspectJ it is a reserved keyword. So I renamed your package to aop.

  • Your pointcut call(* service.apiInnerService(..)) is wrong, you forgot the class name and should use call(* service.MainService.apiInnerService(..)) instead.

  • A native AspectJ aspect should not have a @Component annotation, because that is used for Spring AOP proxy-based aspects. You should avoid Spring to pick it up a second time.

In addition to these changes, I also removed some cruft from your code, reformatted everything a bit and added a main method to AppConfig, so I could easily run the applicaion from my IDE and verify that the aspect works. But it should work the same in your WAR.

When running the application, now I see:

Before Around :testAspectPointcut
Innerservice
After Around
Success

I.e., the aspect is working, intercepting your private method call. But allow me to say that if you need to apply aspects to private methods, you most likely have a design problem in your application.

CodePudding user response:

This version works:

@Aspect
public class ProfileCallAspect {
    private static final Logger LOGGER = LogManager.getLogger(ProfileCallAspect.class);
    
    @Pointcut("call(* org.springframework.jdbc.core.JdbcTemplate.query*(..)) || call(* org.springframework.jdbc.core.JdbcTemplate.update*(..))")
    public void profileQuery() {
    }

    @Around("profileQuery()")
    public Object profile(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        LOGGER.info("ProfileCallAspect() Before");
        Object res =  thisJoinPoint.proceed();
        LOGGER.info("ProfileCallAspect() After");
        return res ;
    }

}

In a Spring project, you can't make it a @Component because of the "call" in the pointcut, but @Configurable works (enabling by @EnableSpringConfigured and with spring-aspects in the dependencies). As Aspect, it works without, but if you want to do something more useful than just logging you may need to inject dependencies in it. Of course, any exception during the proceed() and the "after" will not be logged, if you want that you should replace the @Around by entries: @Before @After, @AfterReturning, @AfterThrowing according to your needs. You also need the build with aspectj-maven-plugin and spring-aspects as aspectLibrary in your pom.xml. (or the equiv. for gradle)

CodePudding user response:

I got this working after removing in pom.xml.

instead of

<pluginManagement> 
  <plugins>
    <plugin>
    </plugin>
  </plugins>
</pluginManagement> 

I changed to

 <plugins>
    <plugin>
    </plugin>
 </plugins>

In fact, the initial approach was a mistake I made in pom.xml

One point if any one else having weaving issues even after proper configuration : Compile the project outside the IDE you are using, If you build the project from IDE there will be overrides for AJC (AspectJ compiler) and the weaving might not happen

  • Related