This tutorial doesn't talk much about how modules fit in the injector tree except for the this phrase:
All requests bubble up to the root NgModule injector that we
configured with the bootstrapModule method.
I think you are looking for https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#q-module-provider-visibility
Why is a service provided in a feature module visible everywhere? Providers listed in the @NgModule.providers of a bootstrapped module have application scope. Adding a service provider to @NgModule.providers effectively publishes the service to the entire application.
When we import a module, Angular adds the module's service providers (the contents of its providers list) to the application root injector.
This makes the provider visible to every class in the application that knows the provider's lookup token.
This is by design. Extensibility through module imports is a primary goal of the Angular module system. Merging module providers into the application injector makes it easy for a module library to enrich the entire application with new services. By adding the HttpModule once, every application component can make http requests.
However, this can feel like an unwelcome surprise if you are expecting the module's services to be visible only to the components declared by that feature module. If the HeroModule provides the HeroService and the root AppModule imports HeroModule, any class that knows the HeroService type can inject that service, not just the classes declared in the HeroModule.
The providers of the modules are added to the root scope. Duplicates are discarded. This means the providers are found from your entire application, except when they are overridden on components or lazy loaded modules. Lazy loaded modules get their own root scope.
If the red module is lazy loaded then component 3 will get the provider from this module, if it's eagerly loaded the providers of the red module are added to the root scope of the application and component 3 will get it from there. This is all related to providers added by
Providers added to
@Directive() are not hoisted to any root scope. DI looks from the component that has a dependendency on its parent and its parents parent, ... for a provider and at last in the root scope of the application or in the root scope of the lazy loaded module if the component is part of one.