Recently, I read some articles and have a deeper understanding about why the advantages of DI. Also, I learned some advanced wiring in Spring.
Why DI
Let’s start with an example. There is a Car class, its dependencies are Trie -> Bottom -> Framework -> Car. Usually, we use constructor to inject dependencies.
1 | class Car { |
However, there would be a bunch of new object()
when you want to create a new Car instance.
1 | int size = 40; |
Imagine what if there are thousands of dependencies. Some old services have this issue. In this case It is hard to maintain or test. What DI does is to reduce the steps of creating instances. IoC(Inversion of Control) containers does this for us. IoC is similar to a factory. You can directly ask for IoC container to get an instance when you need it.
DI way to do it:
1 |
|
Therefore there are two benefits:
- Reduce the steps of creating instances. Also, you don’t have to care about how many parameters in the constructors
- Easy to test. With DI, you just need to mock the dependencies.
Advanced Wiring
Addressing ambiguity in autowiring
Suppose that you have annotated the following setDessert() method with @Autowired. Because all three implementations are annotated by @Component, they’re all picked up during component-scanning and created as beans in the Spring application context. Then, when Spring tries to autowire the Dessert parameter in setDessert(), it doesn’t have a single, unambiguous choice.
1 |
|
Designating a primary bean
With @Primary, in the event of any ambiguity, Spring will choose the primary bean over any other candidate beans.
1 |
|
But what if there are two primary Dessert. This poses a new ambi- guity issue.
Qualifying autowired beans
The @Qualifier annotation is the main way to work with qualifiers. It can be applied alongside @Autowired or @Inject at the point of injection to specify which bean you want to be injected.
1 |
|
The parameter given to @Qualifier is the ID of the bean that you want to inject. All @Component-annotated classes will be created as beans whose ID is the uncapitalized class name. Therefore, @Qualifier(“iceCream”) refers to the bean created when component-scanning created an instance of the IceCream class.
Instead of relying on the bean ID as the qualifier, you can assign your own qualifier to a bean. All you need to do is place the @Qualifier annotation on the bean declara- tion. For example, it can be applied alongside @Component like this:
For lack of having specified any other qualifiers, all beans are given a default qualifier that’s the same as their bean ID.
Scoping beans
By default, all beans created in the Spring application context are created as single- tons. That is to say, no matter how many times a given bean is injected into other beans, it’s always the same instance that is injected each time. Spring defines several scopes under which a bean can be created, including the following:
Singleton—One instance of the bean is created for the entire application.
Prototype—One instance of the bean is created every time the bean is injected
into or retrieved from the Spring application context.
Session —In a web application, one instance of the bean is created for each session.
Request—In a web application, one instance of the bean is created for each
request.
To select an alternative type, you can use the @Scope annotation. An example for Prototype is listed in t he following:
1 |
|
In a web application, it may be useful to instantiate a bean that’s shared within the scope of a given request or session. For instance, in a typical e-commerce application, you may have a bean that represents the user’s shopping cart. If the shopping cart bean is a singleton, then all users will be adding products to the same cart. On the other hand, if the shopping cart is prototype-scoped, then products added to the cart in one area of the application may not be available in another part of the application where a different prototype-scoped shopping cart was injected.
Reference: The advantages of DI and Spring in Action
Thank you for reading!