原版地址:http://code.angularjs.org/1.0.2/docs/guide/di

一、Dependency Injection(依赖注入)

  依赖注入(DI)是一个软件设计模式,处理代码如何得到它所依赖的资源。

  关于DI更深层次的讨论,可以参观Dependency Injection(http://en.wikipedia.org/wiki/Dependency_injection),Inversion of Control(http://martinfowler.com/articles/injection.html),也可以参观软件设计模式的书。

  1. DI in a nutshell(简说DI)

  object或者function,只能够通过以下三种方式获取他们依赖的资源:

    1) 可以通过new运算符创建依赖的资源。

    2) 可以通过全局变量查找依赖的资源。

    3) 可以通过参数传入依赖的资源。

  1、2两种方式,并不是最佳的,因为它们对依赖关系进行hard code,这使得修改依赖关系时,不是不可能,但会变得比较复杂。这对于测试来说尤其是个问题,通常在独立测试时,希望能够提供模拟的依赖资源。

  第3种方法相对来说最可行,因为它去除了从组件(component)中定位依赖的责任。依赖仅仅交给组件就可以了。

 
function SomeClass(greeter) {
this.greeter = greeter
} SomeClass.prototype.doSomething = function(name) {
this.greeter.greet(name);
}
 

  上面的例子,SomeClass不用关心定位greeter这个依赖,它仅仅在运行时传递greeter。

  这样是比较合适的,但它将获取依赖资源的责任交给了负责构建SomeClass的代码那里。

  为了管理创建依赖的责任,每一个angular应用都有一个injector(http://code.angularjs.org/1.0.2/docs/api/angular.injector)。injector是一个服务定位器,负责定位并创建依赖的资源。

  请求依赖,解决了hard code的问题,但它意味着injector需要贯穿整个应用。传递injector,会破坏Law of Demeter(http://baike.baidu.com/view/823220.htm)。为了纠正这个问题,我们将依赖查找的责任转给injector。

  上面说了那么多,看看下面经我修改过的例子,合并了原文的两个例子,分别在angular内、外使用inject:

 
<!DOCTYPE HTML>
<html lang="zh-cn" ng-app="MainApp">
<head>
<meta charset="UTF-8">
<title>injector</title>
</head>
<body>
<div ng-controller="MyController">
<button ng-click="sayHello()">Say Hello</button>
</div>
<script src="../angular-1.0.1.js" type="text/javascript"></script>
<script type="text/javascript">
//创建OtherModule这个module,相当于外部的module
var otherModule = angular.module("OtherModule", []);
//教injector如何创建"greeter"
//注意,greeter本身需要依赖$window
otherModule.factory("greeter", function ($window) {
//这里是一个工厂方法,负责创建greet服务
return {
greet:function (text) {
$window.alert(text);
}
};
});
//下面展示在非当前module中,通过injector调用greet方法:
//从module中创建新的injector
//这个步骤通常由angular启动时自动完成。
//必须引入'ng',angular的东东
//故意颠倒顺序,暂时证实这玩意的顺序是无所谓的。。
var injector = angular.injector(['OtherModule','ng']);
//请求greeter这个依赖。
var g = injector.get("greeter");
//直接调用它~
g.greet("Hi~My Little Dada~"); //这里是当前的主app,需要依赖OtherModule
var mainApp = angular.module("MainApp", ["OtherModule"]);
//留意Controller的定义函数的参数,在这里直接注入$scope、greeter。
// greeter服务是在OtherModule中的
mainApp.controller("MyController",function MyController($scope,greeter) {
$scope.sayHello = function() {
greeter.greet("Hello Kitty~~");
};
}
);
//ng-controller已经在背后默默地做了这个事情
//injector.instantiate(MyController); </script>
</body>
</html>
 

  注意,因为有ng-controller,初始化了MyController,它可以满足MyController的所有依赖需要,让MyController无须知道injector的存在。这是一个最好的结果。应用代码简单地请求它所需要的依赖而不需要处理injector。这样设置,不会打破Law of Demeter。

二、Dependency Annotation(依赖注释,说明依赖的方式)

  injector如何知道什么服务需要被注入呢?

  应用开发者需要提供被injector用作解决依赖关系的注释信息。所有angular已有的API函数,都引用了injector,每一个文档中提及的API都是这样。下面是用服务名称信息注释我们的代码的三个等同的方法。

  1. Inferring Dependencies(隐含依赖)

  这是获取依赖资源的最简单的方式,但需要假定function的参数名称与依赖资源的名称一致。

function MyController($scope, greeter) {
...
}

  函数的injector,可以通过检查函数定义并提取函数名称,猜测需要注入的service的名称(functionName.toString(),RegExp)。在上面的例子中,$scope和greeter是两个需要被注入到函数的服务(名称也一致)。

  虽然这样做很简单,但这方法在javascript混淆压缩后就行不通了,因为参数名称会被改变。这让这个方式只能对pretotyping(产品可用性原型模拟测试法,http://www.pretotyping.org/,http://tech.qq.com/a/20120217/000320.htm)和demo应用有作用。

  2. $inject Annotation($inject注释)

  为了允许脚本压缩器重命名函数的方法后,仍然能够注入正确的服务,函数必须通过$inject属性来注释依赖。$inject属性是一个需要注入的服务的名称的数组。

 
var MyController = function(renamed$scope, renamedGreeter) {

     ...

}
//这里依赖的东东,如果不在当前的module中,它还是不认识的。
//需要在当前module中先依赖对应的module。跟之前的例子差不多。但我不知道这是不是正确的方法。
MyController.$inject = ['$scope', 'greeter'];
 

  需要小心的是,$inject的顺序需要与函数声明的参数顺序保持一致。

  这个注释方法,对于controller声明来说是有用的,因为它与函数一起指定注释信息。

  3. inline Annotation(行内注释)

  有时候,不方便使用$inject注释的方式,例如注释directive的时候。

  例如:

someModule.factory('greeter', function($window) {

    ...;

});

  因为需要临时变量(防止压缩后不能使用),所以代码会膨胀为:

var greeterFactory = function(renamed$window) {
...;
};
greeterFactory.$inject = ['$window'];
someModule.factory('greeter', greeterFactory);

  由于这样(代码膨胀),angular还提供了第三种注释风格:

someModule.factory('greeter', ['$window', function(renamed$window) {
...;
}]);

  记住,所有注释风格都是等价的,可以被用在支持injection的angular中的任何地方。

 

三、Where can I user DI?

  DI遍及整个angular。它通常使用在controller和factory方法中。

  1. DI in controllers

  controller是负责(描述)应用行为的类。建议的controller声明方法是:

 
var MyController = function(dep1, dep2) {
...
}
MyController.$inject = ['dep1', 'dep2'];
MyController.prototype.aMethod = function() {
...
}
 

  2. Factory methods

  factory方法是负责创建大多数angular对象。例如directive、service、filter。factory方法注册在module中,建议的factory声明方法是:

 
angualar.module('myModule', []).
config(['depProvider', function(depProvider){
  ...
}]).
factory('serviceId', ['depService', function(depService) {
  ...
}]).
directive('directiveName', ['depService', function(depService) {
  ...
}]).
filter('filterName', ['depService', function(depService) {
  ...
}]).
run(['depService', function(depService) {
  ...
}]);
 
 
 
 
 
 
 
 
 
 
 
 
  1. AngularJs学习笔记--bootstrap
  2. AngularJs学习笔记--html compiler
  3. AngularJs学习笔记--concepts
  4. AngularJs学习笔记--directive
  5. AngularJs学习笔记--expression
  6. AngularJs学习笔记--Forms
  7. AngularJs学习笔记--I18n/L10n
  8. AngularJs学习笔记--IE Compatibility
  9. AngularJs学习笔记--Modules
  10. AngularJs学习笔记--Scope
  11. AngularJs学习笔记--Dependency Injection
  12. AngularJs学习笔记--Understanding the Model Component
  13. AngularJs学习笔记--Understanding the Controller Component
  14. AngularJs学习笔记--E2E Testing
  15. AngularJs学习笔记--Understanding Angular Templates
  16. AngularJs学习笔记--Using $location
  17. AngularJs学习笔记--Creating Services
  18. AngularJs学习笔记--Injecting Services Into Controllers
  19. AngularJs学习笔记--Managing Service Dependencies
  20. AngularJs学习笔记--unit-testing

AngularJs学习笔记--Dependency Injection(DI,依赖注入)的更多相关文章

  1. Angularjs学习笔记(三)----依赖注入

    一.定义 如前所述,$scope对象被神秘的注入到了控制器中,实际上,这是因为控制器声明了它需要$scope,所以AngularJS才会创建并注入它.这套依赖管理系统可以这样总结:"为了正常 ...

  2. AngularJs 学习笔记(三)依赖注入

    一个对象可以通过三种方式来获取对依赖对象的控制权: 1.在内部创建依赖的对象 2.通过全局变量引用这个依赖对象 3.通过参数进行传递(在这里是通过函数参数) AngularJs通过$injector注 ...

  3. go微服务框架kratos学习笔记八 (kratos的依赖注入)

    目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...

  4. Angular4学习笔记(四)- 依赖注入

    概念 依赖注入是一种设计思想,并不是某一类语言所特有的,因此可以参考开涛大神关于学习Java语言的Spring框架时对其的解释: DI-Dependency Injection,即"依赖注入 ...

  5. ASP.NET Core 2 学习笔记(四)依赖注入

    ASP.NET Core使用了大量的依赖注入(Dependency Injection, DI),把控制反转(Inversion Of Control, IoC)运用的相当巧妙.DI可算是ASP.NE ...

  6. Spring学习笔记--Spring配置文件和依赖注入

    Spring配置文件 1.alias:设置别名,为bean设置别名,并且可以设置多个别名; <!-- 设置别名 --> <alias name="user" al ...

  7. 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(六)-- 依赖注入

    本篇将介绍Asp.Net Core中一个非常重要的特性:依赖注入,并展示其简单用法. 第一部分.概念介绍 Dependency Injection:又称依赖注入,简称DI.在以前的开发方式中,层与层之 ...

  8. ASP.NET Core 学习笔记 第三篇 依赖注入框架的使用

    前言 首先感谢小可爱门的支持,写了这个系列的第二篇后,得到了好多人的鼓励,也更加坚定我把这个系列写完的决心,也能更好的督促自己的学习,分享自己的学习成果.还记得上篇文章中最后提及到,假如服务越来越多怎 ...

  9. .net core学习笔记(3)-依赖注入

    .net core 中使用了大量的依赖注入,对依赖注入一直是一知半解,总想不透,项目中用的是一个网上的开源框架,从底层到web层都是用的构造函数依赖注入. 然后了在继承ActionFilterAttr ...

随机推荐

  1. Redis介绍与安装

    一.redis简介 (一)什么是redis 1.redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value 内存数据库. 2.特点:读写性能强悍 支持丰 ...

  2. Java入门系列-27-反射

    咱们可能都用过 Spring AOP ,底层的实现原理是怎样的呢? 反射常用于编写工具,企业级开发要用到的 Mybatis.Spring 等框架,底层的实现都用到了反射.能用好反射,就能提高我们编码的 ...

  3. Centos7 ftp服务器搭建

    1.使用yum安装ftp服务端: yum install -y vsftpd 2.使用yum安装ftp客户端: yum install -y ftp.x86_64 3.开启ftp服务设置开机启动并查看 ...

  4. Golang教程:函数、变参函数

    函数是完成一个特定任务的代码块.一个函数接受输入,对输入进行一些运算并产生输出. 函数声明 在 Go 中声明一个函数的语法为: func functionname(parametername type ...

  5. IE10 CSS Hack(顺便聊聊IE11的CSS Hack)

    一.特性检测:@cc_on 我们可以用IE私有的条件编译(conditional compilation)结合条件注释来提供针对ie10的Hack:该脚本里面的IE排除条件注释,以确保IE6-9不承认 ...

  6. Expression Blend实例中文教程(7) - 动画基础快速入门Animation

    通过前面文章学习,已经对Blend的开发界面,以及控件有了初步的认识.本文将讲述Blend的一个核心功能,动画设计.大家也许注意到,从开篇到现在,所有的文章都是属于快速入门,是因为这些文章,都是我曾经 ...

  7. Ubuntu17.10下编译Openjdk8u

    一开始笔者用的系统和软件版本都是最新的,导致编译了好几次都失败,最后找到解决的办法,现在记录一下编译及解决的方法 避免以后忘记 所用操作系统 Ubuntu17.10 所用软件及版本 make 3.8. ...

  8. asp.net 、C#实现微信企业号OAuth2认证

    以微信企业号作为入口的应用,几乎都会遇到需要应用系统中个人信息和微信用户关联问题.从而进行其他业务处理.目前所做项目采取在企业号通讯录添加自定义字段存入应用系统用户信息表中唯一标识UserGuid进行 ...

  9. 关于开发Cesium造成的电脑风扇狂飙的问题

    最近在开发Cesium的项目,每次一打开浏览器渲染3D 模型.风扇就狂飙起来,进任务管理器查看发现集显使用率100%,独显使用率0%.使用的是集显进行渲染.怪不得风扇会飙起来.既然知道问题所在,解决的 ...

  10. QML Delegate中访问该持有者的方式 附加属性(转载)

    http://blog.csdn.net/yuxiaohen/article/details/17226971   用法很奇葩记录一下,实测可以,用于弱化delegate与持有者的依赖 delegat ...