-->

Angular2 what is providers, when injector create s

2019-09-22 02:48发布

问题:

This question already has an answer here:

  • What are providers in Angular2? 5 answers

I really want to know What is providers? what relationship with DI in angular2?

app.module.ts

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
  ],
  declarations: [
    test,
  ],
  bootstrap: [ AppComponent ],
  providers: [
    userService
  ]
})
export class AppModule { }

test.component.ts

export class TestComponent implements OnInit, OnDestroy {
constructor(public user: userService)
}

In my understanding, provider contains services list token, injector will use these service token to new service instance. service must be registered in providers.

I'm not sure services instance is created by injector or provider? If created by injector, why we need providers?

回答1:

A provider is a strategy for DI to create instances or get values that it needs to pass to constructors or which are requested using injector.get(..).

providers: [
  MyService // short form for
  { provide: MyService, useClass: MyService },

  // create instance of `MyServiceMock` when `MyService` is requested
  { provide: MyService, useClass: MyServiceMock },  

  // redirect to a provider for `MyService` (^^^ use this one on the previous line)
  { provide: MyServiceMock, useExisting: MyService }, 

  // custom code to create an instance
  { provide: MyService, useFactory: (a, b) => new MyMockService(a, b), deps: [Http, new Inject('foo')]},

  { provide: 'foo', useValue: 'bar' }
]

(the value passed to provide: ... is the token to look up providers. The other parameter is the strategy to use to create an instance)

When DI creates an instance of a class it reads the constructor parameters of the class it needs to create an instance of, or the deps parameter of a provider, to figure out what values it needs to pass to that constructor in order to create that instance.

Then it searches for providers that match these required parameter values (by the type of the constructor parameter, or a token assigned to a constructor parameter using the @Inject(...) decorator.

@Injectable() 
class MyService {}

@Component(...) 
class MyComponent {
  constructor(private myService:MyService) {}
}

When Angular needs a MyComponent instance it requests it from DI, for DI to create an instance it needs an instance of MyService to be able to pass it to the constructor. DI looks up a provider for MyService and creates an instance, or if previously one was already created, this one is re-used.

Where providers are registered defines which instance or value is passed to a constructor.
In this example an instance of the components provider would be injected.
If the Component wouldn't have the providers: [MyService] line, then the instance from the provider in @NgModule() would be injected:

@NgModule({
  ...
  providers: [MyService],
})

@Component({
  providers: [MyService], 
}) 
class MyComponent {
  constructor(private myService:MyService) {}
}

Each child component has its own injector which is a child injector of the parent components injector. When a component is created, DI looks for providers in the components injector, then in the parents component injector, ..., up too AppComponent, and then on the @MgModule() injectors. The first injector that has a provider for the required token is used to get an instance. This means it matters where you provide a provider. If you add a provider to a component, you get as many instances of the provided service, as there are component instances. If you add a provider only to @NgModule(...) class AppModule{} then there will only be a single instance in your whole application.

Lazy-loaded modules add some additional complexity. Check the docs for more details.



回答2:

The service is not created by Injector. When you create a Service you use the @Injectable annotation only when you want to inject another service in the annotated service.

Every service has to be in the providers array. If you declare it in the module.ts you will have the same instance in every Component. If you declare it in the providers array in a Component, that instance will only be accesable to that Component and every child component of it.



回答3:

Just for understanding.

1- Providers are simple classes which should be singleton

2- When any provider(class) is injected in an injectable component it asks component's injector to provide injected class instance by sending key of that class

3- If injector has that singleton instance against that key it returns the instance.

4- Otherwise it creates the instance and register that instance as singleton

A very good example of this is Http service that is injected in different services