1. 程式人生 > >理解angular中的module和injector,即依賴註入

理解angular中的module和injector,即依賴註入

特性 onf nco evel 容器 意義 log 需要 ica

依賴註入(DI)的好處不再贅言,使用過spring框架的都知道。angularjs作為前臺js框架,也提供了對DI的支持,這是javascript/jquery不具備的特性。angularjs中與DI相關有angular.module()、angular.injector()、 $injector、$provide。對於一個DI容器來說,必須具備3個要素:服務的註冊、依賴關系的聲明、對象的獲取。比如spring中,服務的註冊是通過xml配置文件的<bean>[email protected]@[email protected]@Component實現的;對象的獲取可以ApplicationContext.getBean()實現;依賴關系的聲明,即可以在xml文件中配置,[email protected]

/* */lar中,module和$provide相當於是服務的註冊;injector用來獲取對象(angular會自動完成依賴的註入);依賴關系的聲明在angular中有3種方式。下面從這3個方面,介紹下angular的DI。

1、angular.module()創建、獲取、註冊angular中的模塊

  The angular.module() is a global place for creating, registering and retrieving Angular modules.When passed two or more arguments, a new module is created. If passed only one argument, an existing module (the name passed as the first argument to module

) is retrieved。(angular.module()是一個用於創建、註冊和檢索模塊的全局位置。當傳遞兩個或多個參數時,會創建一個新的模塊。如果只傳遞一個參數,則檢索現有的模塊(作為第一個參數傳遞給模塊的名稱)。)

// 傳遞參數不止一個,代表新建模塊;空數組代表該模塊不依賴其他模塊
var createModule = angular.module("myModule", []);

// 只有一個參數(模塊名),代表獲取模塊
// 如果模塊不存在,angular框架會拋異常
var getModule = angular.module("myModule");

// true,都是同一個模塊
alert(createModule == getModule);

  該函數既可以創建新的模塊,也可以獲取已有模塊,是創建還是獲取,通過參數的個數來區分。

  angular.module(name, [requires], [configFn]);

    name:字符串類型,代表模塊的名稱;

    requires:字符串的數組,代表該模塊依賴的其他模塊列表,如果不依賴其他模塊,用空數組即可;

    configFn:用來對該模塊進行一些配置。

  現在我們知道如何創建、獲取模塊了,那麽模塊究竟是什麽呢?官方的Developer Guide上只有一句話:You can think of a module as a container for the different parts of your app – controllers, services, filters, directives, etc.(你可以把模塊看作是應用程序的不同部分的容器——控制器、服務、過濾器、指令)

2、$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.

  之前提到過:module和provide是用來註冊服務到injector中的。查看官方的API,可以看到$provide提供了provide()、constant()、value()、factory()、service()來創建各種不同性質的服務;angular.Module中也提供了這5個服務註冊方法。其實2者功能是完全一樣的,就是用來向DI容器註冊服務到injector中。

  官方API下的auto有$provide 和 $injector,Implicit module which gets automatically added to each $injector.按照字面意思是說,每一個injector都有這2個隱含的服務。但1.2.25版本中,感覺沒有辦法獲取injector中的$provide。不知道這是為什麽?一般來說也不需要顯示使用這個服務,直接使用module中提供的API即可。

var injector = angular.injector();
alert(injector.has("$provide"));//false
alert(injector.has("$injector"));//true

3、angular.injector()

  使用angular.injector();也能獲取到註入器,但是沒有和模塊綁定。這種做法是沒有意義的,相當於是你創建了一個空的DI容器,裏面都沒有服務別人怎麽用呢。正確的做法是,在創建註入器的時候,指定需要加載的模塊。

// 創建myModule模塊、註冊服務
var myModule = angular.module(‘myModule‘, []);
myModule.service(‘myService‘, function() {
            this.my = 0;
});

// 創建herModule模塊、註冊服務
var herModule = angular.module(‘herModule‘, []);
herModule.service(‘herService‘, function() {
            this.her = 1;
});

// 加載了2個模塊中的服務
var injector = angular.injector(["myModule","herModule"]);
alert(injector.get("myService").my);
alert(injector.get("herService").her);

  如果加載了多個模塊,那麽通過返回的injector可以獲取到多個模塊下的服務。這個例子中如果只加載了myMoudle,那麽得到的injector就不能訪問herMoudle下的服務。這裏特別需要註意下:angular.injector()可以調用多次,每次都返回新建的injector對象

var injector1 = angular.injector(["myModule","herModule"]);
var injector2 = angular.injector(["myModule","herModule"]);

alert(injector1 == injector2);//false

4、angular中三種聲明依賴的方式

  angular提供了3種獲取依賴的方式:inference、annotation、inline方式。

// 創建myModule模塊、註冊服務
var myModule = angular.module(‘myModule‘, []);
myModule.service(‘myService‘, function() {
            this.my = 0;
});

// 獲取injector
var injector = angular.injector(["myModule"]);

// 第一種inference
injector.invoke(function(myService){alert(myService.my);});

// 第二種annotation
function explicit(serviceA) {alert(serviceA.my);};
explicit.$inject = [‘myService‘];
injector.invoke(explicit);

// 第三種inline
injector.invoke([‘myService‘, function(serviceA){alert(serviceA.my);}]);

  其中annotation和inline方式,對於函數參數名稱沒有要求,是推薦的做法;inference方式強制要求參數名稱和服務名稱一致,如果JS代碼經過壓縮或者混淆,那麽功能會出問題,不建議使用這種方式。

理解angular中的module和injector,即依賴註入