導入
インジェクターは、たとえば自動パラメーターインジェクションを実行するために使用されます
関数fn($ http、$ scope、aservice){}ngが実行されると、$ http、$ scope、aserviceは、実行のパラメーターとして自動的に渡されます。
実際にそれを理解するのは簡単です、インジェクターは2つのことをしました
次のソースコードでは、上記の2つのことを実装する方法を分析します。
構造
createInjector -> createInternalInjector return: instanceInjector
したがって、createinjector()はInstanceInjectorを返します。構造は次のとおりです。
{invoke:voke:invoke、instantiate:instantiate、get:getservice、annotate:annotate、has:function(name){return providercache.hasownproperty(name + providersuffix)|| cache.hasownproperty(name); }}ソースコード分析
1。CreateInjector
関数CreateInjector(moduleStoload、strictdi){strictdi =(strictdi === true); var instantiating = {}、providersuffix = 'provider'、path = []、loadedmodules = new hashmap([]、true)、// preconfigure $は、loadmodulesのコール登録サービスを提供します。 supportObject(value)、constant:supportobject(constant)、decorator:decorator}}、// providerinjector、instanceinjector 2つのインジェクター// Instanceinjectorはサービスおよびその他の注入を提供します。 $ injectorminerr( 'unpr'、 "unknown provider:{0}"、path.join( '< - '); strictdi)、instanceCache =(instanceCache。 providersuffix) //モジュールforeach(loadmodules(modulestoload)、function(fn){instanceinjector.invoke(fn || noop);}); InstanceInjectorを返します;}2。$供給
$ arting:{provider:supportobject(provider)、factory:supportobject(factory)、service:supportobject(service)、value:supportobject(value)、constant:supportobject(constant)、decorator:decorator}2.1 SupportObject
パッケージング方法の場合、パッケージの前の方法は2つのパラメーター(キー、値)を受け入れます。パッケージ化されたメソッドは、通過するオブジェクトパラメーター、つまり複数のキー - >値をサポートできます。
function supportObject(delegate){return function(key、value){if(isobject(key)){foreach(key、ruvelparams(delegate)); } else {return delegate(key、value); }};}2.2プロバイダー
プロバイダー、サービス、工場の使用方法を確認します
App.Factory( 'ServicEname'、function(){return {getName:function(){}、setName:function(){}}}); app.service( 'servicename'、function(){this.getName = function(){} this.setName = function function($ httpprovider){// $ httpprovider this。$ get = function(){getname:function(){}、setname:function(){}}); assertnothasownproperty(name、 'service'); // provider_がfnまたはarrayの場合、他のプロバイダーをパラメーターに注入できます// providerinjector.instantiate(provider_)を他のプロバイダーに渡すことができるため、//これはプロバイダーとサービスとファクトリーの方法の違いです。 } if(!provider _。$ get){throw $ injectorminerr( 'pget'、 "provider '{0}'は$ get Factory Method。"、name)を定義する必要があります。 } return providercache [name + providersuffix] = provider _;} function factory(name、factoryfn){return provider(name、{$ get:factoryfn}); } function service(name、constructor){return factory(name、['$ injector'、function($ injector){return $ injector.instantiate(constructor);}]);} function value(name、val){return factory(name、valuefn(val)); }最後に、プロバイダーの実装に要約され、プロバイダーをProviderCacheにキャッシュして呼び出します
他とは異なるのは、ProviderCacheとInstanceCacheでそれぞれ保存される定数の実装であるため、プロバイダーとサービスの両方を挿入できます。
関数定数(name、value){assertnothasownproperty(name、 'constant'); ProviderCache [name] = value; instancecache [name] = value;}2.3 LoadModulesを確認します
関数runinvokequeue(queue){var i、ii; for(i = 0、ii = queue.length; i <ii; i ++){var invokeargs = queue [i]、provider = providerinjector.get(invokeargs [0]); //キューの形式は[$ sultion、工場、引数]に保存されます//交換後、$ sultion.factory.apply($ sultion、arguments); // $ Provid Factory、サービス、およびその他のプロバイダー[Invokeargs [1]]を呼び出すことです。 }}2.4デコレーター
例:
module.config(function($ dext){$ sultion.decorator( 'mail'、function($ delegate){$ delegate.addcc = function(cc){this.cc.push(cc);}; return $ delegate;});})この例を使用して、渡されたパラメーター$デリゲートが元のサービスインスタンスであることがわかります。このインスタンスにメソッドを追加する必要があります。これはいわゆるデコレーターです。
ソースコード:
function Decorator(ServicEname、decorfn){var ortigprovider = providerInjector.get(servicename + providersuffix)、orig $ get = origprovider。$ get; origprovider。$ get = function(){//上記のプロバイダーを介して必要なサービスインスタンスを生成し、$ DELEGATE VAR ORIGINSTANCE = INSTANCEINJECTOR.INVOKE(ORIG $ get、Origprovider)でパラメーターリストに挿入します。 InstanceInjector.invokeをreturn(decorfn、null、{$ delegate:originstance}); };}3。Internalinjectorを作成します
3.1全体の構造
//キャッシュからそれを取得します。そうでない場合は、工場に電話して作成します。詳細については、GetService分析を参照してください
関数create internalinjector(cache、factory){function getservice(servicename){} function invoke(fn、self、locals、servicename){} function intentiate(type、locals、servicename){} return {// execute fn、invoke:invoke:intantimeatize get the get the proked: //注入メソッドのパラメーターリストを取得します注釈:アノテート、//プロバイダーまたはサービスが含まれているかどうかを確認してください:function(name){return providercache.hasownproperty(name + providersuffix)|| cache.hasownproperty(name); }};}3.2注釈
FNのパラメーターリストを取得します
// type1Function fn(a、b、c) - > ['a'、 'b'、 'c'] // type2 ['a'、 'b'、fn] - > ['a'、 'b'] // type3function fn(){} fn。$ inject = ['a'、 'c']ソースコード:
function annotate(fn、strictdi、name){var $ inject、fntext、argdecl、last; if(typeof fn === 'function'){if(!($ inject =fn。$ inject)){$ inject = []; if(fn.length){// if(strictdi){if(!isstring(name)||!name){name = fn.name || anonfn(fn); }スロー$ injectorminerr( 'strictdi'、 '{0}は明示的な注釈を使用しておらず、Strictモードで呼び出すことはできません'、名前); } //コメントを削除fntext = fn.toString()。 //すべてのパラメーターfn(a、b、c、d) - > 'a、b、c、d' argdecl = fntext.match(fn_args); // array foreach(argdecl [1] .split(fn_arg_split)、function(arg){arg.replace(fn_arg、function(all、underscore、name){$ inject.push(name);});}); }); } fn。$ inject = $ inject; }} else if(isarray(fn)){last = fn.length -1; assertargfn(fn [last]、 'fn'); $ inject = fn.slice(0、last); } else {assertargfn(fn、 'fn'、true); } $ inject;}を返します3.3 GetService
//キャッシュにサービスがない場合は、elseを入力して、キャッシュ[servicename] =インスタンス化してマークを作成します//次のコールファクトリー(serviceName)であるため、実際に再帰コール// function(servicename){// varider = providerinjector.get(servicename + providersuffix); servicename); //} // instanceinjector.invoke(プロバイダー。$ getは注入して注入する必要があるパラメーターを取得します//したがって、マークをマークすると、円形依存関係getService(servicename)があるかどうかを判断できます{if(cache.hasownporty(servicename)) $ injectorminerr({0} '、serviceName.join(' < - ')) (err){cache [servicename] === delete cache [servicename];3.4呼び出し
関数Invoke(fn、self、locals、servicename){if(typeof locals === 'string'){servicename = locals;地元の人= null; } var args = []、//パラメーターリストを取得$ inject = annotate(fn、strictdi、servicename)、length、i、key; for(i = 0、length = $ inject.length; i <length; i ++){key = $ inject [i]; if(typeof key!== 'string'){throw $ injectorminerr( 'itkn'、 '誤ったインジェクショントークン! } //地元のPriority args.push(locals && locals.hasownproperty(key)?locals [key]:getservice(key)); } if(isArray(fn)){fn = fn [length]; } return fn.apply(self、args);}3.5インスタンス
function instantiate(type、locals、servicename){var constructor = function(){}、instance、returnedValue; //タイプが配列の場合、['$ window'、function($ win){}] constructor.prototype =(isarray(type)?type [type.length -1]:type).prototype;などの最後のパラメーターを取得します。 instance = new Constructor(); //呼び出し呼び出して、typeメソッドを実行してreturnedvalue = invoke(type、instance、locals、servicename)を実行します。 return isobject(returnedValue)|| IsFunction(returnedValue)? returnedValue:instance;}インスタンス化の機能は、タイプをインスタンス化することであり、インスタンス化プロセス中にパラメーターをコンストラクターに自動的に渡すことができます。