Dependency Injection (DI) is so that you avoid having a complicated tree of dependencies.
Imagen having a tree like structure where A instantiates class B and class B instantiates class C, then A instantiates D and D instantiates E.
A --> B ---> C
\
\--> D ---> E
This is all fine fine, until class E needs class C.
Then we need to re arrange everything and instantiate C higher up and pass it through class B and D down to both sides.
This is where DI comes into play.
We instead decide that A instantiates all classes
A --> B
--> C
--> D
--> E
So A is the owner of all classes, and he can then pass in any class to any class to meet whatever demand any class has.
This is what the Spring context
does with the help of the @Autowire
annotation. You declare for spring what class you want to be passed in the instantiated classes. Then Spring during startup, will instantiate all classes and then figure out what class should be fitted where (this is massive simplification). All classes will per default be instantiated as singletons (but this can be customised).
When spring instantiates you class it is called a spring managed bean
. Spring manages the lifecycle of it. Not you, because you are not using new
, the framework is.
During this process Spring does a number of checks and also instantiates in a specific order, configuration classes first, then @Bean
annotated classes, and lastly @Component
, @Service
etc (overly simplifying this here), it will scan for what classes that should be instantiated, it will decide upon an order in which should be instantiated first, then which classes should be @Autowired
into which classes. There are a number of help annotations that will assist Spring during this phase.
@Qualifier
is one, you basically name a class, then you can tell spring where you want it @Autowired
.
It's very useful if you have two singletons configured differently but they have the same name.