Dependency Injection in Angular
In Software Engineering, Dependency Injection means whereby one object supplies the dependencies of another object.
Dependencies are object that can be used as a services.
An injection is the process for passing of a dependency to a dependent object (a client) that would use it.
Dependency Injection is the heart of an Angular applications.
Dependency Injection is a combination of two terms , those are Dependency and Injections.
The Dependency that we are injecting in a constructor is an object of the class that we want to use.
Dependencies are services or objects that can be used in any another object.
Injection is a way to process of passing the dependency to a dependent object. It creates a new instance of class along with its required dependencies.
What is DI?
It allows us to inject dependencies in different components across our applications, without needing to know, how those dependencies are created, or what dependencies they need themselves.
The DI system in angular basically consist of two important aspects:
Angular Injector creates and injects the service and here is the component that needs the service instance.
How does this Angular injector know about our Service?
We need to register our service with the Angular injector. To register the service with our Angular injector we use the providers property of
@NgModule decorator or
@Component decorator. So this means we can register a service with the Angular injector at a component level or at a module level.
A provider is a mechanism using which we register our dependency to be injected. Providers are usually singleton (one instance) objects, that other objects have access to through dependency injection (DI).
Types of Providers
In Angular, we have to register our dependency at two levels.
At App Level
To Register the dependency at app level it creates the injected dependency singleton.
App Level means we use this in
app.module.ts file so we can use this anywhere. We don’t need to use in every components.
At Component Level
We can register the dependency at component level too. There,
a new instance of the dependency will create.
Drawbacks of not using DI
Here, The Mobile Class is dependent on three other classes namely Processor, Display and Camera.
All these three classes are being initialized with in the constructor of the Mobile class itself.
If changes are made to the dependent classes, corresponding changes needs to be made in the Mobile class as well. This clearly show that code is not flexible. Each time you make change in the dependency you will have to modify the mobile class as well.
In this, Instances of dependencies created by a class that needs those dependencies are local to the class and cannot share data and logic.
Also, This code can not be used for Testing purposes. The reason is that , when you are testing, you gives various different parameters and check whether your application is functioning correctly or not so in this Testing can not be used.
Difficult to mock the Processor, display and Camera Object, so unit testing Mobile class can get complex.
DI as a Design Pattern
It is a coding pattern in which a class receives it’s dependencies from external source rather than creating them itself.
Let's Take an example using service
With DI, It is very easy to mock objects when unit testing. This is one of the greatest benefits of DI.
To configure an injector with a service provider using
@Injectable()decorator marks it as a service for creating service instance and that can be injected into the AppComponent.
Here is our
AppComponent and this component has a dependency on
TechService. So this component specifies it’s dependency by using a constructor parameter like this.
TechServiceare passes as a parameter to the constructor rather than instantiating it within the constructor itself.
We have an external source that is creating and injecting the dependencies required by the
AppComponentclass Whenever those dependencies changed the
AppComponentClass need not change.
The Angular injector now will look at this constructor and says alright you have a dependency on
Component Property to the
Template to show the list -
Benefits of DI
Create applications that are easy to write and maintain overtime as the application evolves.
As the Angular injector provides a Singleton i.e A single instance of the service, so it's easy to share data and functionality.
As the dependencies can be mocked so it's easy to write and maintain unit tests.
We can concludes that using DI makes the code very efficient and usable. Binds Loosely coupled component effectively. Increases Modularity. Applications become flexible and robust and Also it is easy to test and maintain your application.