Issue
How does constructor method dependency injection work if I'm not even initializing the class anywhere or passing in arguments. Does Spring take care of this somewhere for me? Would really like to know more about this, if anyone wouldn't mind sharing/teaching me. How does this work on the heap? Would there be a reference to the class being constructed and the dependency so I would have two instances of different objects or just one? I found this answer How does constructor dependency injection work?, but it doesn't really answer my question in great detail.
Example:
@Controller
@RequestMapping
public class SampleController{
private final SomeRepository someRepository;
pulbic SampleController(SomeRepository someRepository) throws Exception{
// will someRepository ever be null?
if(someRepository == null)
throw new Exception("I told you it wouldn't work!");
this.someRepository = someRepository;
}
Solution
Answering your question: yes. Spring manages all the Beans on your behalf. You can declare a Bean in multiple ways:
- XML (the old way);
- Using
@Bean
(but in this case you would actually instantiate the Bean); - Using
@Component
,@Service
,@Repository
or@Controller
(the later 3 are basically specializations of the first).
In your case, you have annotated SampleController
with @Controller
, so now Spring knows that it will need to provide this Bean for you by managing it in the Spring IoC container. However, so that Spring can create the Bean it will also understand that it needs another Bean to be available, in your case SomeRepository
. If such a Bean already exists in Spring IoC Container then Spring provides it to your SampleController
constructor. For this to work, SomeRepository
must also be a Spring-managed Bean, and thus defined by one of the previous three ways.
It is worth mentioning that if for example you would have multiple SomeRepository
Beans in your application (imagine an interface having multiple implementations, being each one a different Bean), you would need to "tell" Spring which one you want to be used in SampleController
, otherwise you would get an error. There are multiple ways to do this:
- Using
@Qualifier
annotations; - Using
@Primary
on one of the implementations to mark it as the "default" in case you don't explicitly "say" which one you want.
You can check examples in https://www.baeldung.com/spring-qualifier-annotation.
This is a very high-level description, but you can find some good articles online about this or even check the reference documentation.
Answered By - João Dias