Angular: dynamic dependency injection and static dependency injection

Problem Description:

When the service dependencies you write are injected into the component, they are initialized directly in the constructor.

Until I saw the private injector written by a certain guy in the code : Injector 

Dynamic dependency injection and static dependency injection

In Angular, using constructor injection to inject services into components is a static dependency injection method. This approach requires explicitly declaring the type of the service in the component's constructor, and having Angular's dependency injection system automatically create and inject instances of the service.

For example, in the following code:

import { Component } from '@angular/core';
import { MyService } from './my.service';

@Component({
  selector: 'app-root',
  template: '<h1>{
   
   { message }}</h1>',
  providers: [MyService]
})
export class AppComponent {
  message: string;

  constructor(private myService: MyService) {
    this.message = this.myService.getMessage();
  }
}

We declared `MyService` in the `providers` array and injected `MyService` into the `myService` parameter in the constructor of the `AppComponent` component. The advantage of this is that dependencies can be checked at compile time and ensure that dependencies have been correctly registered and injected. The disadvantage is that dependencies need to be declared explicitly, and if dependencies change, the code needs to be updated manually.

In contrast, dynamically obtaining service instances at runtime allows for more flexible management of dependencies. For example, in the following code:

import { Component, Injector } from '@angular/core';
import { MyService } from './my.service';

@Component({
  selector: 'app-root',
  template: '<h1>{
   
   { message }}</h1>'
})
export class AppComponent {
  message: string;

  constructor(private injector: Injector) {
    const myService = this.injector.get(MyService);
    this.message = myService.getMessage();
  }
}

We use `Injector` to obtain a service instance named `MyService`, and call the `getMessage` method of the service to obtain the message, and then display the message in the template. The advantage of this is that the service instance can be obtained dynamically at runtime and avoids the problem of explicitly declaring dependencies. The disadvantage is that dependencies require manual management and are prone to runtime errors.

"The disadvantage is that dependencies need to be managed manually." I don't understand this sentence. Doesn't the static dependency injection method also require all services to be declared in the constructor?

In the static dependency injection method, we need to explicitly declare the type of the service in the component's constructor, and Angular's dependency injection system will automatically create and inject instances of the service. This approach requires us to manually manage the services on which the component depends, and we need to manually update the dependencies in the constructor when the service changes.

In contrast, by dynamically obtaining service instances at runtime, we can manage dependencies more flexibly. For example, we can obtain different service instances based on different conditions, or dynamically add or delete service instances at runtime, etc. This approach gives us more flexibility in managing dependencies in our application and avoids some of the limitations that come with explicitly declaring dependencies in components.

I want to know how Angular's Injector dynamically obtains service instances at runtime?

When Angular resolves dependencies, it checks the type of each dependency and attempts to create an instance of that type. If the type is an injectable service, the service's constructor parameters are examined and dependencies on these parameters are resolved recursively. This process continues until all dependencies are created.

When creating a dependency, Angular determines whether it needs to create an instance of the dependency based on the following factors:

1. Whether the dependency has been created: If the dependency has been created, Angular does not need to create it again. Instead, it directly returns the previously created instance.

2. Whether the dependency is optional: If the dependency is optional and is not registered in any module or component, Angular will set it to `null`. Otherwise, it will throw an error.

3. Whether the dependency can be circularly dependent: If there is a circular dependency between the dependency and other dependencies, Angular will throw an error.

4. Whether the dependency can be resolved: If the dependency's type cannot be resolved (for example, due to missing necessary metadata), then Angular will throw an error.

To sum up, Angular will determine whether it needs to create an instance of the dependency based on its type, whether it has already been created, and other factors. If the dependency is necessary and all creation conditions are met, Angular creates an instance of the dependency and returns it to the component or directive.

"For reuse in subsequent requests" What do subsequent requests mean?

In an Angular application, each time a service instance is created, Angular caches it for reuse in subsequent requests. "Request" here refers to a request to the service instance , such as calling a method or property of the service in a component, directive, or other service.

For example, suppose we have a service called `MyService` which provides a method called `getMessage` to get a message. When we use `MyService` in a component, Angular will automatically create an instance of `MyService` and cache it. If we call the `getMessage` method multiple times in the same component, Angular will reuse the previously created `MyService` instance instead of creating a new instance each time.

This caching mechanism improves performance and ensures that all components and directives use the same service instance. Also, because service instances are singletons, they can share data and state across the entire application.

Guess you like

Origin blog.csdn.net/dongnihao/article/details/131899872