Let’s say I have ten controllers that want to autowire to ten services. The controllers and services act very similarly, they just differ in the type of object or DTO they deal with (and the DTOs themselves are very similar too). So I create an abstract controller like so:
public abstract class BaseController<S extends BaseService, D extends BaseDTO> {
@Autowired
protected S service;
@GetMapping("/getThing")
public D getThing(@PathVariable id) {
Object thing = service.getById(id);
// ...convert thing to DTO
return dto;
}
}
I put the @RestController annotation on the subclasses.
Then, I also create an abstract service:
public abstract class BaseService<R extends JpaRepository<O extends Object, Long>> {
@Autowired
protected R repository;
public O getById(Long id) {
return repository.findOne(id);
}
}
And I put @Service on the subclasses.
So the purpose of extending the BaseRepository and BaseService is to provide the actual classes of the DTO and Repository into the generics of the abstract classes.
When I do this, I get the following warning:
Could not autowire. No beans of 'S' type found.
Same warning for ‘R’ for my BaseService.
But when I build and run, the autowiring seems to work fine. My controller and my service works. And when I debug to check the actual bean that got autowired, they seem to be of the correct types.
I have tried moving @Service to BaseService, and also on both BaseService and the subclasses, but it doesn’t seem to change anything.
I understand that in typical cases, constructor injection is preferred. However, if I do that, I’d have to implement very similar constructors ten times for each controller or service. Yes, I do know that constructor injection is still preferred for other reasons. And I understand that the error is technically valid. But for my question, what I want to focus on is this:
Do the inner-workings of Spring really work properly if I autowire it like this? If so, then what is the reason that the warning gets generated? And if code brevity is my utmost concern, then is my best solution to just suppress the warning using @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
?
Kamehamehachoo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.