소개
인젝터는 예를 들어 자동 매개 변수 주입을 수행하는 데 사용됩니다.
함수 fn ($ http, $ scope, aservice) {}NG가 실행되면 $ http, $ scope, aservice는 자동으로 실행을위한 매개 변수로 전달됩니다.
실제로 알아 내기가 쉽습니다. 인젝터는 두 가지를했습니다.
다음 소스 코드는 위의 두 가지를 구현하는 방법을 분석합니다.
구조
createInjector -> createInternalInjector return: instanceInjector
따라서 createInjector ()는 인스턴스 인젝터를 반환하면 구조는 다음과 같습니다.
{호출 : Instantiate : Instantiate, Get : GetService, Annotate : Annotate, has : function (name) {return providercache.hasownproperty (name + providersuffix) || CACHE.HASOWNPROPERTY (이름); }}소스 코드 분석
1
함수 createInjector (modulestoload, strictdi) {strictdi = (strictdi === true); var instantiating = {}, providersuffix = 'provider', path = [], loadedModules = new Hashmap ([], true), // pre-configure $ loadmodules 등의 통화 등록 서비스를 제공합니다. ProviderCache = {$ provider : onsportobject (provider : factory), Service) supportObject (value), constant : supportObject (constant), decorator : decorator}}, // providerinjector, instanceInjector // 인스턴스 인젝터는 외부에서 서비스 및 기타 주입을 제공하며 제공자는 내부적으로 제공자를 제공하여 제공자에게 제공합니다. $ injectorminerr ( 'pross', "알 수없는 공급자 : {0}", path.join ( '<-'), strictdi); instancecache = {} (InstanceCache. returnInjector.invoke (제공자 $ get, 제공자, 정의되지 않은, serviceName); // loading module foreach (loadModules (modulestolOad), function (fn) {instanceInjector.invoke (fn || noop);}); return instanceinjector;}2. $ 제공
$ 제공 : {공급자 : supporoBject (제공자), 공장 : supportObject (Factory), Service : SupportObject (서비스), 값 : supportObject (value), 상수 : supportObject (Constant), Decorator}2.1 SupportObject
포장 방법의 경우 포장 전의 방법은 두 개의 매개 변수 (키, 값)를 수용합니다. 패키지 메소드는 전달되는 객체 매개 변수, 즉 여러 키 -> 값을 지원할 수 있습니다.
함수 supportObject (delegate) {return function (key, value) {if (isobject (key)) {foreach (key, reverseparams (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 () {}); App.Provider ( 'servicename', function ($ httpprovider) {// $ httpprovider this. AssertNothasOwnProperty (이름, '서비스'); // Provider_가 FN 또는 배열 일 때, 다른 공급자는 매개 변수에 주입 될 수 있습니다. // providerInjector.instantiate (provider_)를 //에 의존하는 다른 공급자에게 전달 될 수 있기 때문에 (provider _) {provider _) verfider _ = provider _); } if (! provider _. $ get) {trash $ injectorminerr ( 'pget', "provider '{0}'$ get factory method.", name); } return providerCache [name + providersUffix] = 제공자 _;} 함수 공장 (이름, factoryfn) {return provider (이름, {$ get : factoryfn}); } function service (이름, 생성자) {return factory (이름, [$ 인젝터 ', 함수 ($ Injector) {return $ injector.instantiate (생성자);}];} 함수 값 (이름, val) {return factory (name, valuefn (valefn)); }마지막으로 공급자의 구현에 요약되어 공급자를 공급자를 위해 공급자를 캐시합니다.
다른 것과는 다른 점은 제공자와 서비스를 모두 주입 할 수 있도록 PruessCache 및 InstanceCache에 각각 저장되는 Constant의 구현입니다.
함수 상수 (이름, 값) {AssertNothasOwnProperty (이름, 'constant'); ProviderCache [name] = value; instancecache [name] = value;}2.3 리뷰 하중 모드를 검토하십시오
함수 runinvokequeue (대기열) {var i, ii; for (i = 0, ii = queue.length; i <ii; i ++) {var invokeargs = queue [i], provider = providerinjector.get (invokeargs [0]); // 대기열의 형식은 [$ prowe, factory, arguments]에 저장됩니다. // 교체 후, $ provery.Apply ($ provery, arguments); // $ prosed Factory, Service 및 기타 제공 업체에 전화하는 것입니다 [Invokeargs [1]]. Apply (제공자, invokeargs [2]); }}2.4 데코레이터
예:
module.config (function ($ prose) {$ prose.Decorator ( 'mail', function ($ delegate) {$ delegate.addcc = function (cc) {this.cc.push (cc);}; return $ delegate;});})예제를 사용하면 전달 된 Parameter $ Delegate가 원래 서비스 인스턴스임을 알 수 있으며 소위 데코레이터 인이 인스턴스에 메소드를 추가해야합니다.
소스 코드 :
함수 데코레이터 (ServiceName, DecorFn) {var origprovider = prudiderInjector.get (serviceName + ProvidersUffix), orig $ get = origprovider. $ get; ar return instanceNjector.invoke (decorfn, null, {$ delegate : originstance}); };}3. InternalInjector를 작성하십시오
3.1 전체 구조
// 캐시에서 가져 오십시오. 그렇지 않은 경우 공장에 전화하여 생성하십시오. 자세한 내용은 GetService 분석을 참조하십시오
함수 CreateInternalInjector (캐시, 공장) {함수 getService (serviceName) {} 함수 호출 (fn, self, locals, serviceName) {} function instantiate (유형, 로컬, ServiceName) {} return {// execute fn, invoke, invoke, fn, Instantiate : Instantiate 또는 service, instant, geter, geter get, instantize, instantize, instantize, instantize // 주입 메소드의 매개 변수 목록 가져 오기 : Annotate : // 제공자 또는 서비스가 포함되어 있는지 확인하십시오 : function (name) {return providercache.hasownProperty (name + providersUffix) || CACHE.HASOWNPROPERTY (이름); }};}3.2 주석
fn의 매개 변수 목록을 가져옵니다
// type1function fn (a, b, c) -> [ 'a', 'b', 'c'] // type2 [ 'a', 'b', fn] -> [ 'a', 'b'] // type3function fn () {} fn. $ inject = [ 'a', 'c' -> [ 'a', 'c']소스 코드 :
함수 annotate (fn, strictdi, name) {var $ inject, fntext, argdecl, last; if (fn === 'function') {if (! ($ inject = fn. $ inject)) {$ inject = []; if (fn.length) {// if (strictdi) {if (! isstring (name) ||! name) {name = fn.name || anonfn (fn); } trash $ injectorminerr ( 'strictdi', '{0}은 명시적인 주석을 사용하지 않으며 엄격한 모드에서 호출 할 수 없습니다', 이름); } // 주석을 제거합니다. fntext = fn.tostring (). Replare (strip_comments, ''); // 모든 매개 변수를 선택합니다. 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, 밑줄, 이름) {$ 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); } return $ Inject;}3.3 GetService
// 캐시에 서비스가 없을 때, else, cache [serviceName] = 마크를 만들기 위해 Instantiating // 다음 호출 공장 (serviceName)이기 때문에 실제로 재귀적인 호출 // function (serviceName) {// var provider = providerInjector.get (serviceName + providersUffix); serviceName); //} // instanceinjector.invoke (제공자. $ get는 주입 해야하는 매개 변수를 꺼내서 표시 한 후에 표시 한 후에는 원형 의존성 기능 GetService (serviceName)가 있는지 여부를 결정할 수 있습니다 (cache.hasOwnproperty (serviceName)) $ injectorminerr ( 'CDEP', '<-')는 CACHE를 반환합니다 (err) {cache [serviceName] === instantiation {serviceName}};3.4 호출
함수 호출 (fn, self, 현지인, serviceName) {if (typeof locals === 'string') {serviceName = locals; 지역 주민 = null; } var args = [], // 매개 변수 목록을 가져옵니다. $ inject = annotate (fn, strictdi, serviceName), 길이, i, 키; for (i = 0, length = $ inject.length; i <length; i ++) {key = $ inject [i]; if (typeof key! == 'string') {throw $ injectorminerr ( 'itkn', '잘못된 사출 토큰! 예상 서비스 이름으로, got {0}', key); } // 현지인 우선 순위 args.push (locals && locals.hasownproperty (key)? locals [key] : getService (key)); } if (isArray (fn)) {fn = fn [길이]; } return fn.apply (self, args);}3.5 인스턴스
함수 Instantiate (type, locals, serviceName) {var constructor = function () {}, 인스턴스, returnedValue; // 유형이 배열 일 때 : [ '$ window', function ($ win) {}] 생성자 .prototype = (isarray (type)? type [type.length -1] : type) .prototype; 인스턴스 = 새 생성자 (); // 유형 메소드를 실행하려면 호출 호출 retureDValue = invoke (유형, 인스턴스, 로컬, ServiceName); 반환 isobject (returnedValue) || isfunction (returnedValue)? ReturnEdValue : 인스턴스;}Instantiate의 기능은 유형을 인스턴스화하는 것이며 인스턴스화 프로세스 중에 매개 변수를 생성자로 자동 전달할 수 있습니다.