Angular Dependency Injection Explained

Angular Dependency Injection Explained

Overview

Dependency Injection: Design Patterns

Dependency: An object of a certain type that is required by the program.

Dependency Injection Framework: An Engineering Framework

Injector: Use its API to create instances of dependencies

Provider: How to create? (Constructor, engineering function)

Object: components, dependencies required by modules

Advanced Dependency Injection => The dependency injection framework in Angular provides parent-child hierarchical injection type dependencies

1. Dependency Injection

class Id {
  static getInstance(type: string): Id {
    return new Id();
  }
}

class Address {
  constructor(provice, city, district, street) {}
}

class Person {
  id: Id;
  address: Address;
  constructor() {
    this.id = Id.getInstance("idcard");
    this.address = new Address("Beijing", "Background", "Chaoyang District", "xx Street");
  }
}

Problem: Person needs to know the implementation details of Address and Id.

After ID and Address are refactored, Person needs to know how to refactor.

As the project scales up, integration problems are more likely to occur.

class Id {
  static getInstance(type: string): Id {
    return new Id();
  }
}

class Address {
  constructor(provice, city, district, street) {}
}

class Person {
  id: Id;
  address: Address;
  constructor(id: Id, address: Address) {
    this.id = id;
    this.address = address;
  }
}

main(){
  //Push the construction dependent object to the previous level, where it is called const id = Id.getInstance("idcard");
  const address = new Address("Beijing", "Background", "Chaoyang District", "xx Street");
  const person = new Person(id, address);
}

Person no longer knows the details of Id and Address.

This is the simplest form of dependency injection.

The problem is that you still need to know the details in main.

Idea: Push up one level at a time until you reach the entry function, which handles the construction of all objects. After construction, the subclass is provided to all dependent submodules.

Problem: Entry functions are difficult to maintain. So a dependency injection framework is needed to help.

2. Angular's Dependency Injection Framework

Starting from v5, it has been deprecated due to its slow speed and the introduction of a lot of code, and has been replaced by Injector.create.

ReflectiveInjector : Used to instantiate objects and resolve dependencies. import { Component ,ReflectiveInjector } from "@angular/core"; resolveAndCreate receives a provider array, which tells the injector how to construct the object.

constructor() {
    //Receive a provider array const injector = ReflectiveInjector.resolveAndCreate([
      {
        provide:Person, useClass:Person
      },
      {
        provide: Address, useFactory: ()=>{
          if (environment.production) {
            return new Address("Beijing", "Background", "Chaoyang District", "No. xx, xx Street");
          }else{
            return new Address("Tibet", "Lhasa", "xx District", "xx Street xx No.");
          }
        }
      },
      {
        provide:Id, useFactory:()=>{
          return Id.getInstance('idcard');
        }
      }
    ]);
  }

Injector:

The injector is equivalent to the main function and can get everything in the dependency pool.

import { Component ,ReflectiveInjector, Inject} from "@angular/core";
import { OverlayContainer } from "@angular/cdk/overlay";
import { Identifiers } from "@angular/compiler";
import { stagger } from "@angular/animations";
import { environment } from 'src/environments/environment';

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"]
})
export class AppComponent {

  constructor(private oc: OverlayContainer) {
    //Receive a provider array const injector = ReflectiveInjector.resolveAndCreate([
      {
        provide:Person, useClass:Person
      },
      {
        provide: Address, useFactory: ()=>{
          if (environment.production) {
            return new Address("Beijing", "Background", "Chaoyang District", "No. xx, xx Street");
          }else{
            return new Address("Tibet", "Lhasa", "xx District", "xx Street xx No.");
          }
        }
      },
      {
        provide:Id, useFactory:()=>{
          return Id.getInstance('idcard');
        }
      }
    ]);
    const person = injector.get(Person);
    console.log(JSON.stringify(person));
  }

}

class Id {
  static getInstance(type: string): Id {
    return new Id();
  }
}

class Address {
  provice: string;
  city: string;
  district:string;
  street:string;
  constructor(provice, city, district, street) {
    this.provice=provice;
    this.city=city;
    this.district=district;
    this.street=street;
  }
}

class Person {
  id: Id;
  address: Address;
  constructor(@Inject(Id) id, @Inject(Address )address) {
    this.id = id;
    this.address = address;
  }
}

You can see that the console prints out the person information.

Abbreviation:

 // {
      // provide: Person, useClass: Person
      // },
      Person, //abbreviated as Person

In the Angular framework, the framework does a lot of things, and things registered in the provider array are automatically registered in the pool.

@NgModule({
  imports: [HttpClientModule, SharedModule, AppRoutingModule, BrowserAnimationsModule],
  declarations: [components],
  exports: [components, AppRoutingModule, BrowserAnimationsModule],
  providers:
    {provide:'BASE_CONFIG',useValue:'http://localhost:3000'}
  ]
})
  constructor(@Inject('BASE_CONFIG') config) {
    console.log(config); //The console prints out http://localhost:3000
  }

Angular is a singleton by default, if you want a new instance to be injected each time. There are two ways.

First, when returning, return a method instead of an object.

{
    provide: Address, useFactory: ()=>{
        return ()=>{
            if (environment.production) {
                return new Address("Beijing", "Background", "Chaoyang District", "No. xx, xx Street");
            }else{
                return new Address("Tibet", "Lhasa", "xx District", "xx Street xx No.");
            }
        }
    }
},

2. Use parent-child Injector.

constructor(private oc: OverlayContainer) {
    //Receive a provider array const injector = ReflectiveInjector.resolveAndCreate([
      Person,
      {
        provide: Address, useFactory: ()=>{
          if (environment.production) {
            return new Address("Beijing", "Background", "Chaoyang District", "No. xx, xx Street");
          }else{
            return new Address("Tibet", "Lhasa", "xx District", "xx Street xx No.");
          }
        }
      },
      {
        provide:Id, useFactory:()=>{
          return Id.getInstance('idcard');
        }
      }
    ]);

    const childInjector = injector.resolveAndCreateChild([Person]);

    const person = injector.get(Person);
    console.log(JSON.stringify(person));
    const personFromChild = childInjector.get(Person);
    console.log(person===personFromChild); //false
  }

If the child injector does not find the dependency, it will look for it in the parent injector.

The above is the detailed explanation of Angular dependency injection. For more information about Angular, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Detailed explanation of the singleton mode of angular service (under dependency injection mode)
  • Deep understanding of dependency injection in Angular
  • Angular 4 Dependency Injection Learning Tutorial: Use of InjectToken (VIII)
  • Angular 4 Dependency Injection Learning Tutorial: Use of ValueProvider (Part 7)
  • AngularJS Learning Part 2 AngularJS Dependency Injection
  • AngularJS dependency injection example analysis (using module and injector)
  • Self-study to implement angularjs dependency injection
  • Detailed Analysis of Dependency Injection $injector in Angular.JS Learning
  • AngularJS $injector Dependency Injection Detailed Explanation

<<:  Detailed example of sorting function field() in MySQL

>>:  Windows 10 installation vmware14 tutorial diagram

Recommend

Vue simple implementation of turntable lottery

This article shares the specific code of Vue to s...

How to ensure the overall user experience

Related Articles: Website Design for User Experien...

How to install Nginx in Docker

Install Nginx on Docker Nginx is a high-performan...

How to implement Mysql switching data storage directory

How to implement Mysql switching data storage dir...

HTML image img tag_Powernode Java Academy

summary Project description format <img src=&q...

MySQL Workbench download and use tutorial detailed explanation

1. Download MySQL Workbench Workbench is a graphi...

JS asynchronous code unit testing magic Promise

Table of contents Preface Promise chaining MDN Er...

Detailed explanation of how to use several timers in CocosCreator

1. setTimeOut Print abc after 3 seconds. Execute ...

Vue realizes simple effect of running light

This article shares the specific code of Vue to a...

A preliminary understanding of CSS custom properties

Today, CSS preprocessors are the standard for web...

How to use node to implement static file caching

Table of contents cache Cache location classifica...

Detailed explanation of basic data types in mysql8.0.19

mysql basic data types Overview of common MySQL d...

Detailed steps and problem solving methods for installing MySQL 8.0.19 on Linux

I recently bought a Tencent Cloud server and buil...

Share 8 MySQL pitfalls that you have to mention

MySQL is easy to install, fast and has rich funct...