I’ve encountered a rather tricky bug while injecting a dependency in a Spring Boot application:
|
|
In most cases this exception is caused by injecting a bean which was enhanced by a Spring aspect into a field referencing an implementation instead on an interface. This was not the case in my setup.
The setup
We have an Interface:
A service implementing the interface:
And a service injecting the interface as a dependency:
At no point are we trying to inject a concrete class (DependencyImpl) instead on an interface (Dependency), so this couldn’t have been the problem.
The solution
It turns out the problem lies with the @Resource annotation. There are some (subtle) differences between injecting dependencies with @Resource and @Autowired.
To quote the Spring reference guide:
@Resource is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process. @Autowired has rather different semantics: After selecting candidate beans by type, the specified String qualifier value is considered within those type-selected candidates only.
In short:
@Resource tries to inject a bean named ‘dependency’, which in this setup is of type DependencyImpl
@Autowired tries to inject a bean with type ‘Dependency’, of which we have one: DependencyImpl
Our fixed turns out to be rather simple for this case, replace @Resource with @Autowired: