The benefits of dependency injection (DI) will not be discussed anymore, and those who have used the spring framework know it. As a foreground js framework, angularjs also provides support for DI, which is a feature that javascript/jquery does not have. DI related to angularjs include angular.module(), angular.injector(), $injector, and $provide. For a DI container, it must have three elements: service registration, dependency declaration, and object acquisition. For example, in spring, the registration of the service is implemented through the <bean> tag of the xml configuration file or the annotation @Repository, @Service, @Controller, and @Component; the acquisition of the object can be implemented by ApplicationContext.getBean(); the declaration of dependencies can be configured in the xml file, or it can be declared in the java code using @Resource and other annotations. In angular, module and $provide are equivalent to the registration of the service; injector is used to obtain objects (angular will automatically complete the injection of dependencies); there are 3 ways to declare dependencies in angular. The following is an introduction to angular DI from these 3 aspects.
1. angular.module() creates, obtains, and registers modules in 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.
// Passing more than one parameter means a new module; an empty array means that the module does not rely on other modules var createModule = angular.module("myModule", []);// There is only one parameter (module name), which means to get the module // If the module does not exist, the angular framework will throw an exception var getModule = angular.module("myModule");// true, all of the same module alert(createModule == getModule);This function can create new modules or obtain existing modules. Whether to create or obtain, it is distinguished by the number of parameters.
angular.module(name, [requires], [configFn]);
name: string type, representing the name of the module;
Requires: an array of strings, representing the list of other modules that the module depends on. If you do not rely on other modules, use an empty array;
configFn: Used to make some configurations to this module.
Now we know how to create and obtain modules, so what exactly are modules? There is only one sentence on the official Developer Guide: You can think of a module as a container for the different parts of your app controllers, services, filters, directives, etc. I don’t quite understand it now. It roughly means that a module is a collection of some functions, such as a whole composed of child elements such as controllers, services, filters, instructions, etc. I can't explain it now, so I'll leave it behind first.
2. The relationship between $provide and module
The $provide service has a number of methods for registering components with the $injector. Many of these functions are also exposed on angular.Module.
As mentioned earlier: module and provide are used to register services into injector. Check the official API and you can see that $provide provides provide(), constant(), value(), factory(), and service() to create services of various natures; angular.Module also provides these 5 service registration methods. In fact, the functions of the two are exactly the same, which is used to register services with the DI container into the injector.
Auto under the official API includes $provide and $injector, Implicit module which gets automatically added to each $injector. Literally, each injector has these 2 implicit services. But in version 1.2.25, I feel that there is no way to get the $provide in the injector. I don't know why this is? Generally speaking, you don't need to display this service, just use the API provided in the module.
var injector = angular.injector();alert(injector.has("$provide"));//falsealert(injector.has("$injector"));//true3. angular.injector()
You can also get the injector using angular.injector(); but it is not bound to the module. This approach is meaningless, it is equivalent to creating an empty DI container, and there is no service in it, how can others use it? The correct way is to specify the modules that need to be loaded when creating the injector.
// Create myModule module and register the service var myModule = angular.module('myModule', []);myModule.service('myService', function() { this.my = 0;});// Create herModule module and register the service var herModule = angular.module('herModule', []);herModule.service('herService', function() { this.her = 1;});// Load the service var injector = angular.injector(["myModule","herModule"]);alert(injector.get("myService").my);alert(injector.get("herService").her);If multiple modules are loaded, the services under multiple modules can be obtained through the returned injector. In this example, if only myMoudle is loaded, the obtained injector cannot access the services under herMoudle. It is particularly important to note here: angular.injector() can be called multiple times, and each time it returns the newly created injector object.
var injector1 = angular.injector(["myModule","herModule"]);var injector2 = angular.injector(["myModule","herModule"]);alert(injector1 == injector2);//false
4. Three ways to declare dependencies in angular
angular provides three ways to obtain dependencies: inference, annotation, and inline methods.
// Create myModule module and register the service var myModule = angular.module('myModule', []);myModule.service('myService', function() { this.my = 0;});// Get injectorvar injector = angular.injector(["myModule"]);// The first inferenceinjector.invoke(function(myService){alert(myService.my);});// The second annotationfunction explicit(serviceA) {alert(serviceA.my);};explicit.$inject = ['myService'];injector.invoke(explicit);// The third type of inlineinjector.invoke(['myService', function(serviceA){alert(serviceA.my);}]);Among them, the annotation and inline methods do not require the function parameter name, which is recommended; the inference method requires that the parameter name and the service name are consistent. If the JS code is compressed or obfuscated, then there will be problems with the function, and this method is not recommended.
The above is a compilation of the information injected by AngularJS dependency. We will continue to add relevant information in the future. Thank you for your support for this website!