Angular Study Notes 4: Dependency Injection and Services

1. Dependency injection

(1) Dependency injection understanding

  1. Let’s look at a piece of code first:
class Engine {
    
    
    // Engine类的构造函数,需要接受一个number类型的参数
    constructor(speed: number) {
    
    
    }
}

class Car {
    
    
    private engine: Engine; // 声明一个私有属性,类型为Engine
    constructor() {
    
    
        // 在构造函数中实例化Engine
        this.engine = new Engine(200);
    }
}

In this code, Carthere is a private attribute in the class engine, which is Enginean instance object of the class. At this time, the creation process of this attribute will heavily rely on Enginethe definition of the class. If Enginethe number or type of parameters that the class needs to accept changes, you need to immediately Modify enginethe attribute creation code. The coupling of the code is too high.

  1. Dependency injection is a concept proposed to reduce code coupling. Dependency Injection, or DI for short, the container is responsible for the dependencies between classes. Look at the following piece of code:
class Engine {
    
    
    constructor(speed: number) {
    
    }
}
// 在类的外部实例化Engine类
const engine = new Engine(200);
class Car {
    
    
    private engine: Engine;
    constructor(engine: Engine) {
    
    
        // 直接使用
        this.engine = engine;
        console.log(engine)
    }
}
const car = new Car(engine)

Create it outside the class engine, so that Carthe class does not need to worry engineabout the parameter passing problem, and there is no need to Enginecouple with the class. The object creation process Angularhas been implemented internally for us, so when we use the service, we do not need to create it again. We only need to constructordeclare it in the parameter list and use variables to receive it.

(2) Creation and use of Injector

  1. Concept
    Angular has its own DI framework to help us implement class instantiation. We can implement complex dependency injection with simple code.
    Angular's DI framework mainly has four important concepts:
    1. Dependency The instance object on which the component depends, that is, the instance object of the service
    2. Token Gets the identity of the service instance object. Angular maintains a lot of instance objects internally. When obtaining, you need to use Token to determine which instance object you want to obtain.
    3. Injector is responsible for maintaining and creating instance objects, and finding the instance objects needed by the component and passing them to the component through parameters.
    4. Provider object used to configure the injector, specify the class to create the service instance object, and specify the Token
  2. Injector
    1. Create an injector
      and introduce the ReflectiveInjector module into the app.moudule.ts root module.
    import {
          
          ReflectiveInjector} from '@angular/core';
    
    Virtualize a service class and create an injector
    class injectorService {
          
          
    constructor() {
          
          }
    run(){
          
          
            console.log('run')
        }
    }
    
    // 创建注入器,接受一个数组,数组里放服务类
    const injector = ReflectiveInjector.resolveAndCreate([injectorService])
    
    1. Get the service instance and run the instance method
    // 向get中传递Token标识,Token就是这个类,返回值就是这个类的实例对象
    const myInjector = injector.get(injectorService)
    myInjector.run()
    
    Methods for the console to successfully run the instance:
    Insert image description here
    3. The same injector will not repeatedly create an instance of a service. The instance will be cached when it is created, so the service is in singleton mode.
    const myInjector1 = injector.get(injectorService)
    const myInjector2 = injector.get(injectorService)
    console.log(myInjector1 === myInjector2) // true
    
    1. Different injectors create different instances
    // 创建子级注入器
    const childInjector = injector.resolveAndCreateChild([injectorService])
    const myInjector1 = injector.get(injectorService)
    const myInjector3 = childInjector.get(injectorService)
    console.log(myInjector1 === myInjector3) // false
    
    1. The way the injector searches for service instances is similar to the scope chain. When it is not found in the current injector, it will search for the parent injector. If it cannot find it, a new instance will be created.
    // 创建注入器
    const injector = ReflectiveInjector.resolveAndCreate([injectorService])
    // 子级注入器不传服务
    const childInjector = injector.resolveAndCreateChild([])
    const myInjector1 = injector.get(injectorService)
    // 当前注入器中没有找到,会向上级注入器查找
    const myInjector3 = childInjector.get(injectorService)
    console.log(myInjector1 === myInjector3)  // true
    
  3. The form of creating an injector on Provider
    is actually a shorthand method. Let’s look at the complete writing method.
    Obtain the identifier of the instance object through Provide specification, which is the token. When provide and useClass are the same, you can write the class directly
    	const injector = ReflectiveInjector.resolveAndCreate([{
          
          
    	    provide: "myInjectorService",
    	    useClass: injectorService
    	}])
    	const myInjector1 = injector.get("myInjectorService")
    
    useClass indicates that the current injector stores a class.
    The injector can be used not only to store classes, but also to store objects. The objects stored with the injector are often unique and immutable.
    const injector = ReflectiveInjector.resolveAndCreate([{
          
          
        provide: "user",
        useValue: Object.freeze({
          
          
            userName:'张三',
            userToken:'123456'
        })
    }])
    const user = injector.get('user')
    

(2) Service

  1. Creation and introduction of services
    • Use the command line tool provided by cli to create a service: ng g s shared/user , a service will be created under the shared module
      Insert image description here
    • Write service code
      import {
              
               Injectable } from '@angular/core';
      @Injectable({
              
              
        providedIn: 'root'
      })
      export class UserService {
              
              
        constructor() {
              
               }
        getUser() {
              
              
          return {
              
              
            name: '张三',
            age: 20,
            address: '北京市'
          }
        }
      }
      
    • Introduce services into component classes
    import {
          
          UserService} from "../../user.service";
    
    public user = this.userService.getUser();
    ngOnInit() {
          
          
        console.log(this.user)
    }
    

Guess you like

Origin blog.csdn.net/weixin_45855469/article/details/130378270