$injector:
(When you request a service, the $injector is responsible for finding the correct service provider, instantiating it and then calling its $get
service factory function to get the instance of the service.)
$injector用来提供正确的服务provider,实例化服务,然后调用他的$get方法来获取服务实例
//provide源码
function provider(name, provider_) {
if (isFunction(provider_)) {
provider_ = providerInjector.instantiate(provider_);
}
if (!provider_.$get) {
throw Error('Provider ' + name + ' must define $get factory method.');
}
return providerCache[name + providerSuffix] = provider_;
}
1 //service源码
2 function service(name, constructor) {
3
4 return factory(name, ['$injector', function($injector) {
5
6 return $injector.instantiate(constructor);
7
8 }]);
9 }
本例引自 http://www.mamicode.com/info-detail-247448.html
// 创建myModule模块、注册服务
1 var myModule = angular.module('myModule', []);
2 myModule.service('myService', function() {
3 this.my = 0;
4 });
// 创建herModule模块、注册服务
1 var herModule = angular.module('herModule', []);
2 herModule.service('herService', function() {
3 return{her:1}
4 });
// 加载了2个模块中的服务,此处必须传入一个数组,即使只加载一个模块,并且angular.injector()可以调用多次,每次都返回新建的injector对象。
//$injector用法跟此例相同,只不过是作为服务注入到其他服务中去,然后又调用get,invoke等方法实例化其他服务
1 var injector = angular.injector(["myModule","herModule"]);
2
3 alert(injector.get("myService")); //injector.get("myService")会返回一个由myservice作为构造函数创建的对象
4
5 alert(injector.get("herService")); //此处会得到一个由herService返回的{her:1}对象
1 // 获取injector
2 var injector2 = angular.injector(["myModule"]);
3 //invoke与get的区别是一个传入回调函数或数组,一个传入服务名
4 // 第一种inference(如果用压缩工具的话,由于js压缩工具JavaScript minifiers/obfuscators会缩短变量名,因此myservice会被缩短);
5 injector2.invoke( function(myService){ alert(myService); } ); //获取到模块之后调用挂载在模块上的myservice服务,将服务名作为参数传入
6
7 // 第二种annotation
8 function foo(serviceA) {alert(serviceA.my);};
9 foo.$inject = ['myService'];
10 injector2.invoke(foo);
11
12 // 第三种inline
13 injector.invoke(['myService', function(serviceA){alert(serviceA.my);}]); //inline方法其实就是一二方法的结合而已
$provide:
(The $provide service has a number of methods for registering components with the$injector. Many of these functions are also exposed on angular.Module
.)
$provide 服务有一系列的方法(6个方法: provider,value,constant,factory,service,decorator),这些方法用 $injector来注册组件,大部分的方法都暴露在了angular.module下,也就是可以直接在module下调用这些函数。
注意,所有服务都是延迟实例化的。这意味着所有的服务只有在需要时,或者被依赖时才会实例化。换句话说,AngularJS不会实例化服务,除非被请求了或者被应用直接或间接依赖了。
1 provider(name, provider); 2 3 factory(name, $getFn); 4 5 service(name, constructor); 6 7 value(name, value); 8 9 constant(name, value); 10 11 decorator(name, decorator);
provider的第二个参数如果是一个对象(第一种情况),会检索该对象的$get方法,然后调用该方法,最终得到的就是直接调用该方法后的返回值,而不是将该方法作为构造函数返回的新对象。如果第二个参数是函数,则会将该函数作为构造函数创建一个新对象,又再去检索$get方法,和第一种情况相同
factory的第二个参数最终也会作为$get方法返回一个值,而service第二个参数是传入一个构造器,因此只会返回对象(当然也包括数组,函数等)
value服务不能作为依赖注入config()方法中, 也就是 .config( function(value){ } )会报错, 但可作为依赖注入其他服务,并且值可以改变,constant可以注入config()中,但值不可被改变
decorator服务能够修改除constant(否则报错)以外的其他服务,第二个参数必须是一个函数,否则报错,就算修改value服务的值也需要在函数中返回修改后的值;修改service服务是可以返回任何值,不仅限于对象。 使用decorator必须在相应服务定义了之后才能修改,否则会报出找不到相应服务的错误。函数中传入的$delegate代表修改之前服务返回的原始值;
(此外,如controllerProvide.register(name,constructor),$filterProvider等$filterProvider.register(name,factory)可以用来注册一个过滤器,跟在模块上注册服务是一样的;)
run块,config块:
- Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.
- Run blocks - get executed after the injector is created and are used to kickstart the application. Only instances and constants can be injected into run blocks. This is to prevent further system configuration during application run time.
When bootstrapping, first Angular applies all constant definitions. Then Angular applies configuration blocks in the same order they were r egistered.
Run blocks are the closest thing in Angular to the main method. A run block is the code which needs to run to kickstart the application. It is executed after all of the services have been configured and the injector has been created. Run blocks typically contain code which is hard t o unit-test, and for this reason should be declared in isolated modules, so that they can be ignored in the unit-tests.
当引导程序开始时,angular会先运行所有的constant定义,这是为了可以在config运行之前注入config中,接着是config块会按照注册的顺序被执行,最后才是run块在服务配置好和注入器被创建之后执行。