I am new to AOP and currently trying to implement an aspect for controller methods annotated with a custom annotation. I allways get a NullPointerException on repository when myFunction is invoked. It seems that i have two instances of of the controller. One of them is instantiated without autowiring the repository. When i remove @MyAnnotation everything works as expected.
Can you give me any hint on how to force Spring/AspectJ to use my constructor?
My controller looks like:
@RestController
@RequestMapping(value = "/api")
public class MyController {
private Repository repository;
public MyController(Repository repository) {
this.repository = repository;
}
@RequestMapping(value = "/{variable1}", method = GET)
@MyAnnotation
public final FeatureCollection myFunction(
final @PathVariable(required = true) long variable1
) {
repository.findById(variable1);
(...)
}
}
The aspect:
@Aspect
public class MyAspect {
@Around("@annotation(MyAnnotation)")
public Object any(ProceedingJoinPoint pjp) throws Throwable {
return pjp.proceed();
}
}
The configuration:
@Configuration
@EnableAspectJAutoProxy
public class WebConfig {
@Bean
public MyAspect myAspect() {
return new MyAspect();
}
}
It comes from the fact that the annotated method is final
.
If you can remove the final
keyword, it'll work.
If you google something like "spring aop final methods", you'll find more info, but basically, when Spring creates the proxy, it generates a subclass from your original class, to wrap the call to super with your aspect. The problem is that a final method cannot be inherited by the subclass, so that makes it hard for the proxy to work. Therefore, a lot of limitations come from that, and AOP doesn't work that much with final
stuff.
This limitation is mentioned in the docs, I don't think you'll get a workaround for it:
11.6 Proxying mechanisms
...
final
methods cannot be advised, as they cannot be overridden.
Hoping this will help you!