博客
关于我
AngularJS之Dependency Injection(五)
阅读量:412 次
发布时间:2019-03-05

本文共 3115 字,大约阅读时间需要 10 分钟。

AngularJS 依赖注入实战:从装饰器到 $injector

在 AngularJS 开发中,依赖注入是核心机制之一。它允许我们将应用的各个部分(如服务、过滤器、指令等)以声明方式注入到控制器或其他地方,从而实现松耦合和可测试的应用架构。本文将从装饰器(decorator)谈起,深入探讨如何基于 Angular 提供的依赖注入机制来构建和管理应用组件。


装饰器:修改服务而无需修改代码

在 Angular 中,装饰器是一种强大的工具,它允许我们在服务、过滤器或指令被注册之前对它们进行修改。这意味着即使源代码无法修改,我们仍然可以通过装饰器对其进行定制和扩展。

最常见的装饰器用途之一是对日志服务进行自定义。在 Angular 的默认配置中,$log 服务是一个简单的日志记录器。通过装饰器,我们可以在其上添加额外功能,例如在每次日志记录时打印额外信息。

以下是一个典型的装饰器示例:

angular.module('myApp', []).config(['$provide', function($provide) {    $provide.decorator('$log', [        '$delegate',         function($delegate) {            var originalWarn = $delegate.warn;            $delegate.warn = function decoratedWarn(msg) {                msg = 'Decorated Warn: ' + msg;                originalWarn.apply($delegate, arguments);            };            return $delegate;        }    ]);}]);

在这个示例中,装饰器通过拦截 $log 服务的 warn 方法,向其添加了额外的功能。每当 warn 被调用时,会在消息前添加一个固定的字符串。这样,即使不修改源代码,我们也可以在日志输出时添加自定义信息。


通过 $injector 管理组件

在 Angular 应用中,$injector 服务是依赖注入的核心。它负责查找和注入应用中定义的服务、过滤器和指令。通过 $injector,我们可以不仅注入基本服务,还可以动态获取模块中的组件和资源。

$injector 提供了多种方法来管理组件,例如:

  • annotate:获取指定函数的参数注释。
  • get:获取指定服务名称的服务实例。
  • invoke:调用函数并注入所需参数。

以下是一个使用 $injector 注注的示例:

testApp.controller("indexController", function ($scope, $log, $injector) {    var counter = 0;    var logClick = function ($log, $exceptionHandler, message) {        if (counter == 0) {            $log.log(message);            counter++;        } else {            $exceptionHandler("已经点击过了");        }    };    $scope.handleClick = function () {        var deps = $injector.annotate(logClick);        for (var i = 0; i < deps.length; i++) {            console.log("依赖项: " + deps[i]);        }    };});

在这个示例中,$injector.annotate(logClick) 返回了 logClick 函数的所有依赖项。通过遍历这些依赖项,我们可以详细了解哪些服务被注入到函数中。


获取服务通过 $injector

除了通过注入函数参数获取服务,$injector 还提供了获取服务实例的方法。例如,可以通过 $rootElement.injector() 获取根元素所在模块的 $injector

以下是一个动态注入服务的示例:

testApp.controller("indexController", function ($scope, $log, $rootElement) {    var counter = 0;    var logClick = function ($log, $exceptionHandler, message) {        if (counter == 0) {            $log.log(message);            counter++;        } else {            $exceptionHandler("不能再点击啦,点爆啦,哥们!");        }    };    $scope.handleClick = function () {        var localVars = { message: "第一次点击" };        $rootElement.injector().invoke(logClick, null, localVars);    };});

在这个示例中,$rootElement.injector().invoke(logClick, null, localVars) 会动态调用 logClick 函数,并将 localVars 作为参数注入到函数中。


$inject 对比 $injector

在 Angular 中,$inject$injector 是两个常用的依赖注入工具。$inject 更适合在控制器或其他注入位置直接注入服务,而 $injector 则用于程序matic获取服务实例。

以下是一个使用 $inject 的示例:

app.controller('indexCtrl', indexCtrl);indexCtrl.$inject = ['$scope', 'customService'];function indexCtrl($scope, customService) {    // 使用 customService...}

虽然 $inject$injector 看起来很相似,但它们在实现上有细微差别。通常情况下,$inject 会在注入过程中直接获取服务,而 $injector 则用于程序matic操作。


总结

通过本文的学习,我们掌握了 AngularJS 中依赖注入的核心机制,包括装饰器和 $injector 的使用方法。装饰器允许我们在服务、过滤器或指令被注册之前对其进行修改,而 $injector 则提供了程序matic获取和管理依赖项的能力。

在实际开发中,装饰器通常用于定制默认服务(如日志服务),而 $injector 则用于动态注入和管理组件。通过合理使用这些工具,我们可以构建出更灵活、可测试的 Angular 应用。

如果你对 Angular 的依赖注入机制还有其他疑问,欢迎在评论区留言!

转载地址:http://jmlzz.baihongyu.com/

你可能感兴趣的文章
Netty工作笔记0085---TCP粘包拆包内容梳理
查看>>
Netty常用组件一
查看>>
Netty常见组件二
查看>>
netty底层源码探究:启动流程;EventLoop中的selector、线程、任务队列;监听处理accept、read事件流程;
查看>>
Netty心跳检测机制
查看>>
Netty核心模块组件
查看>>
Netty框架内的宝藏:ByteBuf
查看>>
Netty框架的服务端开发中创建EventLoopGroup对象时线程数量源码解析
查看>>
Netty源码—2.Reactor线程模型一
查看>>
Netty源码—3.Reactor线程模型三
查看>>
Netty源码—4.客户端接入流程一
查看>>
Netty源码—4.客户端接入流程二
查看>>
Netty源码—5.Pipeline和Handler一
查看>>
Netty源码—5.Pipeline和Handler二
查看>>
Netty源码—6.ByteBuf原理一
查看>>
Netty源码—6.ByteBuf原理二
查看>>
Netty源码—7.ByteBuf原理三
查看>>
Netty源码—7.ByteBuf原理四
查看>>
Netty源码—8.编解码原理一
查看>>
Netty源码—8.编解码原理二
查看>>