Some quick first impressions I got when browsing your projects before cloning them:
- You should not use Lombok + native AspectJ together in a compile-time weaving scenario, see my answer here.
- Possible workarounds would be multi-phase compilation, i.e. first Java + Lombok and then post-compile-time weaving with AspectJ, see my answer here. Alternatively, use
delombok
in order to first generate source code with Lombok annotations expanded into equivalent source code and then compile the generated sources with AspectJ.
- On a second look, your sample aspect module does not seem to use any Lombok, so you do not need that dependency. But probably your real project does, hence my remarks above.
- Of course, you can use compile-time weaving in order to weave your aspects, as you suggested. You need to correctly configure AspectJ Maven Plugin in this case, though, which you did not. You need to tell it in the Spring Boot module where to find the aspect library and which dependencies to weave, in addition to the main application. Did you ever read the plugin documentation, e.g. chapters Weaving classes in jars, Using aspect libraries and Multi-module use of AspectJ? I also answered tons of related questions here already.
- But actually, the preferred approach for weaving aspects into Spring applications is to use load-time weaving (LTW), as described in the Spring manual. That should be easier to configure and you would not need any AspectJ Maven Plugin stuff and probably would not have any Lombok issues during compilation either.
Judging from your sample projects and the absence of any aspectLibraries
and weaveDependencies
sections in your AspectJ Maven configuration, you simply did not bother to read any documentation, which leaves me to wonder what you did during the one month you tried to get this working.
I would appreaciate a comment, explaining why you want to use CTW instead of LTW. The only reason I can think of is that in addition to your native aspect, you also want to use Spring AOP aspects withing your Spring application. But if you activate native AspectJ LTW, you cannot use Spring AOP at the same time anymore. If that is not an issue, I recommend LTW, as it is documented and tested well in Spring. CTW is no problem either, but more difficult to understand and manage in your POMs.
Update: OK, I did not want to wait any longer for your reason to use CTW and simply decided to show you a LTW solution instead. What I did was:
- Remove AspectJ Maven Plugin and AspectJ Tools from your Spring project
- Add
src/main/resources/org/aspectj/aop.xml
, configuring it to use your aspect and target your base package + subpackages
- Fix pointcut to also use your base package + subpackages, because in your base package there are no classes. This is a typical beginner's mistake. You need to use
execution(* com.ak..*(..))
with ..
, not just com.ak.*
.
Non-essential cosmetics I applied are:
- Call
context.getBean(TestController.class).mainRequest()
from the Spring Boot application's main method in order to automatically produce some aspect output, in order to avoid having to use curl
or a web browser in order to call a local URL.
- Use the Spring application as an auto-closeable via try-with-resources in order to make the application close after creating the desired log output.
- Change the aspect to also log the joinpoint in order to see in the log, which methods it actually intercepts. Otherwise all log lines look the same, which is not quite helpful.
- Use
try-finally
in order to make sure that the log message after proceeding to the original method is also logged in case of an exception.
The diff looks like this (I hope you can read diffs):
diff --git a/aspect-test-project/src/main/java/com/ak/aspect/MethodLogAspect.java b/aspect-test-project/src/main/java/com/ak/aspect/MethodLogAspect.java
--- a/aspect-test-project/src/main/java/com/ak/aspect/MethodLogAspect.java (revision Staged)
+++ b/aspect-test-project/src/main/java/com/ak/aspect/MethodLogAspect.java (date 1626233247623)
@@ -7,14 +7,14 @@
@Aspect
public class MethodLogAspect {
- @Around("@annotation( MethodLog) && (execution(* com.ak.*(..)))")
+ @Around("@annotation(MethodLog) && execution(* com.ak..*(..))")
public Object wrap(final ProceedingJoinPoint joinPoint) throws Throwable {
- System.out.println("***Aspect invoked before calling method***");
-
- final Object obj = joinPoint.proceed();
-
- System.out.println("***Aspect invoked after calling method***");
-
- return obj;
+ System.out.println("[BEFORE] " + joinPoint);
+ try {
+ return joinPoint.proceed();
+ }
+ finally {
+ System.out.println("[AFTER] " + joinPoint);
+ }
}
}
diff --git a/src/main/java/com/ak/ParentprojectSpringbootApplication.java b/src/main/java/com/ak/ParentprojectSpringbootApplication.java
--- a/src/main/java/com/ak/ParentprojectSpringbootApplication.java (revision Staged)
+++ b/src/main/java/com/ak/ParentprojectSpringbootApplication.java (date 1626233555873)
@@ -1,14 +1,17 @@
package com.ak;
+import com.ak.controller.TestController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication(scanBasePackages = { "com.ak.*" })
-//@SpringBootApplication
public class ParentprojectSpringbootApplication {
public static void main(String[] args) {
- SpringApplication.run(ParentprojectSpringbootApplication.class, args);
+ try (ConfigurableApplicationContext context = SpringApplication.run(ParentprojectSpringbootApplication.class, args)) {
+ context.getBean(TestController.class).mainRequest();
+ }
}
}
diff --git a/parentproject-springboot/pom.xml b/parentproject-springboot/pom.xml
--- a/parentproject-springboot/pom.xml (revision Staged)
+++ b/parentproject-springboot/pom.xml (date 1626232421474)
@@ -71,13 +71,6 @@
<version>1.9.6</version>
</dependency>
- <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.6</version>
- </dependency>
-
<dependency>
<groupId>com.ak.aspect</groupId>
<artifactId>aspect-test-project</artifactId>
@@ -100,24 +93,6 @@
</configuration>
</plugin>
- <plugin>
- <groupId>com.nickwongdev</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.12.6</version>
- <configuration>
- <source>11</source>
- <target>11</target>
- <complianceLevel>11</complianceLevel>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
For your convenience, here are the complete changed files:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.ak</groupId>
<artifactId>parentproject-springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>parentproject-springboot</name>
<description>Test project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ak.dependency</groupId>
<artifactId>dependencyprojet</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- aspectj runtime dependency -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>com.ak.aspect</groupId>
<artifactId>aspect-test-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-verbose -showWeaveInfo">
<!-- only weave classes in our application-specific packages -->
<include within="com.ak..*"/>
</weaver>
<aspects>
<aspect name="com.ak.aspect.MethodLogAspect"/>
</aspects>
</aspectj>
package com.ak.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class MethodLogAspect {
@Around("@annotation(MethodLog) && execution(* com.ak..*(..))")
public Object wrap(final ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("[BEFORE] " + joinPoint);
try {
return joinPoint.proceed();
}
finally {
System.out.println("[AFTER] " + joinPoint);
}
}
}
package com.ak;
import com.ak.controller.TestController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication(scanBasePackages = { "com.ak.*" })
public class ParentprojectSpringbootApplication {
public static void main(String[] args) {
try (ConfigurableApplicationContext context = SpringApplication.run(ParentprojectSpringbootApplication.class, args)) {
context.getBean(TestController.class).mainRequest();
}
}
}
Now you simply make sure to add the JVM argument -javaagent:/path/to/aspectjweaver-1.9.6.jar
to your Java command line in order to activate native AspectJ LTW. For more details about how to configure LTW within Spring if more sophisticated ways, please read the Spring manual, section Using AspectJ with Spring Applications.
The console log should look something like this:
[AppClassLoader@3764951d] info AspectJ Weaver Version 1.9.6 built on Tuesday Jul 21, 2020 at 13:30:08 PDT
[AppClassLoader@3764951d] info register classloader jdk.internal.loader.ClassLoaders$AppClassLoader@3764951d
[AppClassLoader@3764951d] info using configuration /C:/Users/alexa/Documents/java-src/SO_AJ_SpringCTWMultiModule_68040124/parentproject-springboot/target/classes/org/aspectj/aop.xml
[AppClassLoader@3764951d] info register aspect com.ak.aspect.MethodLogAspect
[AppClassLoader@3764951d] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
[RestartClassLoader@1f385e10] info AspectJ Weaver Version 1.9.6 built on Tuesday Jul 21, 2020 at 13:30:08 PDT
[RestartClassLoader@1f385e10] info register classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@1f385e10
[RestartClassLoader@1f385e10] info using configuration /C:/Users/alexa/Documents/java-src/SO_AJ_SpringCTWMultiModule_68040124/parentproject-springboot/target/classes/org/aspectj/aop.xml
[RestartClassLoader@1f385e10] info register aspect com.ak.aspect.MethodLogAspect
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.2)
(...)
[RestartClassLoader@1f385e10] weaveinfo Join point 'method-execution(com.ak.dependency.model.AccountInfo com.ak.service.TestService.incomingRequest())' in Type 'com.ak.service.TestService' (TestService.java:20) advised by around advice from 'com.ak.aspect.MethodLogAspect' (MethodLogAspect.java)
[RestartClassLoader@1f385e10] weaveinfo Join point 'method-execution(com.ak.dependency.model.AccountInfo com.ak.dependency.Route.accountInfo())' in Type 'com.ak.dependency.Route' (Route.java:12) advised by around advice from 'com.ak.aspect.MethodLogAspect' (MethodLogAspect.java)
[RestartClassLoader@1f385e10] weaveinfo Join point 'method-execution(com.ak.dependency.model.BalanceInfo com.ak.dependency.Pipeline.balanceInfo())' in Type 'com.ak.dependency.Pipeline' (Pipeline.java:11) advised by around advice from 'com.ak.aspect.MethodLogAspect' (MethodLogAspect.java)
(...)
Controller
[BEFORE] execution(AccountInfo com.ak.service.TestService.incomingRequest())
[BEFORE] execution(AccountInfo com.ak.dependency.Route.accountInfo())
[BEFORE] execution(BalanceInfo com.ak.dependency.Pipeline.balanceInfo())
[AFTER] execution(BalanceInfo com.ak.dependency.Pipeline.balanceInfo())
[AFTER] execution(AccountInfo com.ak.dependency.Route.accountInfo())
[AFTER] execution(AccountInfo com.ak.service.TestService.incomingRequest())
(...)