场景实例
如上代码,run方法依赖注入testervice服务,app模块加载执行run方法的传入的函数时,注入testService实例化的单例对象,在函数执行时,获取获取/设置该对象的属性值,或执行该对象的属性方法。在执行run方法传递的函数时,打印输出a。
下面先看看数据的流动过程,然后分析代码的实现。在js中皆为数据,function也是数据类型的一种。在这里,function和其他数据类型一样,也理解为数据类型。
数据流动
上面的js文件加载后,通过调用angular.module('app')方法获取模块app的模块对象,调用run方法把function(testProvider){console.log (testProvider.a);})放入模块的对象的_runBlocks队列中,然后返回模块对象。调用模块对象的service方法把['$provide','provider',Arguments(2)]放入模块对象的_invokeQueue队列中,其中Argument(2)为调用第8行的 service传入的参数的argumens。
modules.app._runBlocks = [... ,function(testProvider){console.log (testProvider.a);}), ...]
modules.app._invokeQueue = [... ,['$provide','provider',Arguments(2)], ...]
在加载模块的过程中, 会执行modules.app._invokeQueue队列和执行modules.app._runBlocks队列中的函数。
执行完modules.app._invokeQueue后,会把队列的元素转化处理缓存存储在providerCache对象中,
providerCache.testProviderProvider = { $get:function(){ return {a:'a'}; } }
在执行modules.app._runBlocks队列中的函数时,会执行如下函数:
function(testProvider){ console.log(testProvider.a); }
结果输出a。
在执行上面的函数时,先获取testProvider服务,从provideCache.testProviderProvider获得{a:'a'}对象,并且存储在instanceCache对象中,即
instanceCache.testProvider = { a : 'a' }
执行上面函数时,通过apply方法把testProvider对象作为实参传入,函数内部可操作该对象。若下次需依赖注入 testProvider,直接从instanceCache获取该对象。
代码分析
第3875行instanceCache对象用于存储与依赖注入有关的信息。用于实例化服务单例对象和缓存服务对象。第3976行到3980行创建了$injector服务,并且挂载在instanceCache对象上,即instanceCache.$injector。利用闭包特性,服务$injector可以访问第3977行createInternalInjector传的实参。下面看一下,是如何创建$injector服务的。
第4114行到第4135行createInternalInjector函数用于创建$injector服务。在第3977行到第3980行调用该函数后,返回从第4126行到第4134行包含的对象,这个对象即$injector服务。其中invoke函数用于执行使用依赖注入的函数和获取依赖服务的对象,如function(testProvider){}依赖testProvider的函数。get函数用于根据函数的参数的名字获取相应的服务对象,如该对象没有被实例化过,实例化对象并缓存在instanceCache对象中,并返回实例化后的对象。如果依赖注入的对象实例化过,直接从缓存中对象获取并返回。annotate函数返回函数所依赖的依赖服务的形参名组成的数组。
第4114行到第4136行的getService用于根据服务名获取服务实例。
第4138行到第4164行的invoke函数用于执行依赖注入的函数。如上面的函数function(testProvider){}。先获取testProvider服务,然后把testProvider服务的单例对象,作为该函数的实参传入,并执行这个函数。第 4144行获取fn的依赖注入的服务名字,即['testProvider']。第4147行到4157行用于获取函数fn依赖的服务。第4163行把依赖的服务传入函数,并且执行该函数。
providerCache与instanceCache
providerCache缓存对象:
providerCache = { $provide: { provider: supportObject(provider), factory: supportObject(factory), service: supportObject(service), value: supportObject(value), constant: supportObject(constant), decorator: decorator }, $injector:{}, //模块加载时,缓存的一些经过处理后的服务,不是最终的服务对象, //生成的最终对象缓存在instanceCache对象中 testProviderProvider:{ $get: function (){ {a : 'a'} } }, ... }
instanceCache对象:
instanceCache = { $injector: { invoke: invoke, instantiate: instantiate, get: getService, annotate: annotate, has: function(name) { return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); } }, //缓存实例化对象 testProvider: { a : 'a' } ... }
providerCache对象与instanceCache对象贯穿于整个框架,是框架的核心数据。
providerCache对象主要用于模块加载时,操作和缓存注入的provider,service ,factory等服务。
instanceCache对象借助于providerCache对象实现依赖服务的管理。实例化服务,并缓存服务单例对象。