Aspect does not work with Spring boot application with external jar

I am trying to create a timer aspect for measuring the execution time of methods.

I created an annotation named @Timer :

 @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.METHOD, ElementType.TYPE}) public @interface Timer { String value(); } 

And then I created the aspect as follows:

 @Aspect public class MetricAspect { @Autowired private MetricsFactory metricsFactory; @Pointcut("@annotation(my.package.Timer)") public void timerPointcut() {} @Around("timerPointcut() ") public Object measure(ProceedingJoinPoint joinPoint) throws Throwable { /* Aspect logic here */ } private Timer getClassAnnotation(MethodSignature methodSignature) { Timer annotation; Class<?> clazz = methodSignature.getDeclaringType(); annotation = clazz.getAnnotation(Timer.class); return annotation; } 

I have a configuration class as follows:

 @Configuration @EnableAspectJAutoProxy public class MetricsConfiguration { @Bean public MetricAspect notifyAspect() { return new MetricAspect(); } } 

Everything until defined here in a packaged jar that I use as dependencies in my spring boot application

In my spring boot application, I import MetricsConfiguration and I debugged the code and saw that the MetricAspect bean was created.

I use it in code as follows:

 @Service public class MyService { ... @Timer("mymetric") public void foo() { // Some code here... } ... } 

But my code does not reach the measure method. Not sure what I am missing.

To complete the image, I have these dependencies in my pom file:

 <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.7.4</version> </dependency> </dependencies> 

What is the @Configuration class that imports MetricsConfiguration :

 @Configuration @EnableAspectJAutoProxy @Import(MetricsConfiguration.class) @PropertySource("classpath:application.properties") public class ApplicationConfiguration { } 

It boots with automatic spring boot.

+14
java spring aop aspectj
source share
6 answers

can @Component or @Configurable solve your problem?

 @Aspect @Component public class yourAspect { ... } 

Enable Spring AOP or AspectJ

EDIT:

I created a project to simulate your problem, it seems not a problem in the end. Is it affected by another issue?

https://github.com/zerg000000/spring-aspectj-test

+11
source share

I could not reproduce your problem using aspectJ 1.8.8 and spring 4.2.5. Here is my multi-modular maven approach with an aspect in a separate bank.

I changed your code a bit, but did not change the annotations. The only thing that may be different is that I added the org.springframework:spring-aop and defined my entry point as follows:

 @Import(MetricsConfiguration.class) @SpringBootApplication public class Application { // @Bean definitions here // public static void main(String[] args) throws InterruptedException { ApplicationContext ctx = SpringApplication.run(Application.class, args); ctx.getBean(MyService.class).doWork(); } } 
+4
source share

I had a similar problem when the aspect was built in the jar library and the spring boot application was somewhere else. It turns out that the packages for the spring boot application and the jar library were different. Because of this, Spring did not study the library package for automatically connecting to the application context.

So, I had to include @ComponentScan({"base.package.application.*", "base.package.library.*"}) In Application.java.

+2
source share
  1. If the external jar is a Spring boot Starter, you can configure the Aspect bean in AutoConfiguration:

(one)

 @Aspect public class MyAspect { //.... } 

(2)

 package abc @Configuration public class MyAutoConfiguration { @Bean MyAspect myAspect() { return new MyAspect(); } } 

(3) config in spring.factories

 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ abcMyAutoConfiguration 
  1. If the external jar file is not a Spring loader, just load Aspect as a bean, you can use @ComponentScan
+2
source share

Add this Scan component to resolve the problem.

 @ComponentScan("package.of.aspect") @Configuration @EnableAspectJAutoProxy @Import(MetricsConfiguration.class) @PropertySource("classpath:application.properties") public class ApplicationConfiguration { } 
0
source share

According to mojohaus's explanation , you should add assembly settings as shown below for woven your aspect to all classes implementing your aspect interface.

 <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.11</version> <configuration> <complianceLevel>1.8</complianceLevel> <includes> <include>**/*.java</include> <include>**/*.aj</include> </includes> <aspectDirectory>src/main/aspect</aspectDirectory> <testAspectDirectory>src/test/aspect</testAspectDirectory> <XaddSerialVersionUID>true</XaddSerialVersionUID> <showWeaveInfo>true</showWeaveInfo> <aspectLibraries> <aspectLibrary> <groupId>your aspect groupId</groupId> <artifactId>your aspect artifactId</artifactId> </aspectLibrary> </aspectLibraries> </configuration> <executions> <execution> <id>compile_with_aspectj</id> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile_with_aspectj</id> <goals> <goal>test-compile</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>${aspectj.runtime.version}</version> </dependency> <dependency> <groupId>your aspect groupId</groupId> <artifactId>youar aspect artifactId</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> </plugin> </plugins> </build> 
-2
source share

All Articles