Aspect does not work with Spring boot application with external jar
Solution 1
can @Component
or @Configurable
solve your issue?
@Aspect
@Component
public class yourAspect {
...
}
EDIT:
I created a project to simulate your issue, seems no problem after all. Is it affected by other issue?
https://github.com/zerg000000/spring-aspectj-test
Solution 2
I was unable to reproduce your problem using aspectJ 1.8.8 and spring 4.2.5. Here is my maven multi-module approach with aspect in separate jar.
I modified your code slightly but did not change any annotations. The only thing that might be differ is that I've added org.springframework:spring-aop
dependency and defined my entrypoint 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();
}
}
Solution 3
I had a similar problem where the aspect was built in a jar library, and the spring-boot application was else where. Turns out that the packages for the spring-boot application and the jar library were different. Due to which Spring was not looking into the package of the library to autowire into the application context.
So, had to include @ComponentScan({"base.package.application.*", "base.package.library.*"})
in the Application.java
Solution 4
- If the external jar is Spring boot starter, you can config Aspect bean in AutoConfiguration:
(1)
@Aspect
public class MyAspect {
//....
}
(2)
package a.b.c
@Configuration
public class MyAutoConfiguration {
@Bean
MyAspect myAspect() {
return new MyAspect();
}
}
(3)config in spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
a.b.c.MyAutoConfiguration
- If the external jar is not a Spring boot starter, just load Aspect as a bean, you can use @ComponentScan
Related videos on Youtube
Avi
Updated on July 09, 2022Comments
-
Avi almost 2 years
I am trying to create a timer aspect for measuring methods run time.
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 up until here is defined in a packaged jar which I use as a dependency in my spring boot application
In my spring boot application I import the
MetricsConfiguration
and I debugged the code and saw that theMetricAspect
bean is created.I use it in code as follows:
@Service public class MyService { ... @Timer("mymetric") public void foo() { // Some code here... } ... }
But my code doesn't reach to the
measure
method. Not sure what I'm missing.For completing the picture, I have these dependencies in my pom file added:
<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>
That's the
@Configuration
class that importsMetricsConfiguration
:@Configuration @EnableAspectJAutoProxy @Import(MetricsConfiguration.class) @PropertySource("classpath:application.properties") public class ApplicationConfiguration { }
It's loaded with Spring's automagically configuration loading.
-
Harshil Sharma over 7 yearsDo you also have spring-aspects dependency?
-
Avi over 7 yearsI tried adding it and it didn't work as well :/
-
sheltem over 7 yearsWhy are you using reflection to get the annotation? You can simply add it to the parameters of the around advice method and access it directly.
-
Avi over 7 years@kriegaex - I actually created this kind of code in the past many times and it worked. The main difference is the use of spring boot which I mentioned :/
-
Viswanath Lekshmanan over 7 yearsIs
timerPointcut()
method gets invoked ? -
Alex about 5 yearsHi @Avi! How did you fix this problem? I just have the same issue in my project. Thank you!
-
Avi about 5 years@Alex - Unfortunately, I didn't :(
-
-
ka yu Lai over 7 yearsgithub.com/spring-projects/spring-boot/tree/master/… official example of how to use AspectJ in spring boot
-
Avi over 7 yearsThanks for your answer Albert. It's not the
@Component
issue though. I tried for the gist of it but I create the bean inMetricsConfiguration
anyway. It's not the issue. I suspect that's because the aspect and the bean are in an external jar and I'm using spring boot. -
Avi over 7 yearsThanks for your thorough answer. I still couldn't find no difference between my code and yours. My guess is that it's related to the fact that spring loads a
@Configuration
class (actually more than one) automagically and something there gets lost. I will keep digging. -
vsminkov over 7 years@Avi could you show how do you import
MetricsConfiguration
in your application? Is it differs from my example? -
vsminkov over 7 years@Avi well... it seems the same for me :) can you reproduce your problem with small amount of code and post it go github?
-
Aimal Khan almost 6 yearsadding @Component annotation solves the problem and it does makes sense as well cuz the aspect might need to be injected at runtime, any thoughts?