Why aspectj-maven-plugin
ignore my AnnotationInheritor.aj
file? Am I configured something wrong?
I want to advice ItemRepository#getById
with custom annotation:
@Repository
public interface ItemRepository extends JpaRepository<Item, Long> {
// AOP does not work, since autogenerated ItemRepositoryImpl#getById
// won't have @MyAnnotation annotation
@MyAnnotation
public Item getById(Long id);
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnnotation {
}
@Aspect
@Component
public class MyAspects {
@Around("@annotation(MyAnnotation)")
public Object execute(ProceedingJoinPoint joinPoint) {
// This advice works correct when @MyAnnotation is placed on class, I tested.
// The problem is that I have to put @MyAnnotation on interface method
}
}
Spring Data JPA use interfaces and Java annotations are never inherited from interface to subclass (due JVM limitations). To make my advice work with custom annotations there is a little AspectJ trick. So as described at previous referrence, I created AnnotationInheritor.aj
file:
package com.vbakh.somepackage.aspects;
// For some reason does not work. WHY?
public aspect AnnotationInheritor {
declare @method : void ItemRepository+.getById() : @MyAnnotation;
}
And add the following configurations to my pom.xml
:
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<!-- IMPORTANT -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.9</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8 </encoding>
</configuration>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.8.10</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
P.S. Is there any way to perform the same logic without *.aj files? Means with *.java files.
I guess it should work, even without
AnnotationInheritor
made a small demo, have a look...
demo
I copied your code into an AspectJ project (no Spring or Spring AOP there) in order to test it. I found a few problems:
@Around("@annotation(MyAnnotation)")
will not find the annotation because there is no fully qualified class name.declare @method : void ItemRepository+.getById() : @MyAnnotation;
does not match your interface method's signatureItem getById(Long id)
.MyAspects.execute(..)
needs to throwThrowable
and of course also return something, such as the result ofjoinPoint.proceed()
. But maybe that was just sloppy copy & paste.After fixing this, the following MCVE works beautifully:
Helper classes making the project compile:
Marker annotation:
Driver Application:
Aspects:
Just in case you wonder why I added
execution(* *(..))
to the pointcut, this is because I wanted to exclude matchingcall()
joinpoints which are available in AspectJ as opposed to Spring AOP.Console log:
Voilà! It works nicely.
If it does not work for you like this you have other issues such as (but not exclusively)
the "auto-generated
ItemRepositoryImpl#getById
" you mentioned in passing. Whenever and wherever this is generated during the build process, it needs to exist before the aspect is applied to it. In order to analyze this I would need an MCVE on GitHub, though.whether the target code to weave the aspect into is in the same Maven module as the aspect code. If it is not, you need to change your Maven setup.