Skip to content
This repository was archived by the owner on Dec 6, 2017. It is now read-only.

Commit 10e471b

Browse files
author
Anting Shen
committed
refactor: Simpler, Faster injector
BREAKING CHANGE - Calls to StaticInjector and DynamicInjector should be replaced with ModuleInjector - There are no longer StaticInjectors and DynamicInjectors. They have been replaced by a new ModuleInjector class that acts as both types of injectors. There is also a faster NodeInjector class for specific use cases where many injector features aren’t needed. (Miško has more info on NodeInjectors) - ModuleInjectors have no visibility - All bindings and instances of parent injectors are now visible in child injectors. NodeInjectors do, however, have some sense of visibility. - The optional argument “forceNewInstances” of Injector.createChild has been removed Instead, create a new module with bindings of the types that require new instances and pass that to the child injector, and the child injector will create new instances instead of returning the instance of the parent injector. - Use “new ModuleInjector(modules, parent)” instead of “Injector.createChild(modules)” - The latter is still available but deprecated. - Injectors with no parent now have a dummy RootInjector instance as the parent Instead of checking “parent == null”, check for “parent == rootInjector”. - Injectors no longer have a name field - typeFactories have changed - Old type factories had the form (injector) => new Instance(injector.get(dep1), … ) - New factories have one of: - toFactory(a0, a1) => new Instance(a0, a1) - When calling Module.bind(toFactory: factory), there is an additional argument “inject” of a list of types or keys (preferred for performance) whose instances should be passed to the factory. The array “p” passed to the factory function will be instances of the types in “inject”. Example: - Old code. module.bind(Car, toFactory: (i) => new Car(i.get(Engine))); - New code. - module.bind(Car, toFactory: (engine) => new Car(engine), inject: [Engine]); There is also some syntactic sugar for this special case. - Old code. module.bind(Engine, toFactory: (i) => i.get(Engine)); - New code. module.bind(Engine, toFactory: (e) => e, inject: [Engine]); - With sugar. module.bind(Engine, toInstanceOf: Engine); - Modules have a TypeReflector instance attached - The TypeReflector is how the module will find the “toFactory” and “inject” arguments when not explicitly specified. This is either done with mirroring or code generation via transformers. Typical use will not need to worry about this at all, and the default reflector will suffice. If needed, implement TypeReflector and use new Module.withReflector(reflector). - The transformer has been updated - Running the transformer will do the necessary code generation and edits to switch the default TypeReflector from mirroring to static factories. Enable transformer to use static factories, disable to use mirrors. More docs on the transformer can be found in transformer.dart - And it’s lots faster!
1 parent 57523ea commit 10e471b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1833
-1711
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ test/main.dart.js.deps
88
test/main.dart.js.map
99
test/main.dart.precompiled.js
1010
test/transformer/build
11+
benchmark/generated_files/
12+
examples/build
1113
out
1214
build
1315
benchmark/generated_files/*

CHANGELOG.md

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ Added missing library declaration to injector.
3535
- **injector:** optimized module to injector instantiation
3636
([62f22f15](https://github.com/angular/di.dart/commit/62f22f1566642cecc1b9f980475c94a7a88e9362))
3737

38-
3938
# 1.0.0
4039

4140
Starting with this release DI is following [semver](http://semver.org).

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License
22

3-
Copyright (c) 2013 Google, Inc.
3+
Copyright (c) 2014 Google, Inc.
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+13-7
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,29 @@
77
Add dependency to your pubspec.yaml.
88

99
dependencies:
10-
di: ">=0.0.39 <0.1.0"
10+
di: ">=2.0.0 <3.0.0"
1111

1212
Then, run `pub install`.
1313

1414
Import di.
1515

1616
import 'package:di/di.dart';
17-
import 'package:di/auto_injector.dart';
1817

1918
## Example
2019

2120
```dart
2221
import 'package:di/di.dart';
23-
import 'package:di/auto_injector.dart';
2422
2523
abstract class Engine {
2624
go();
2725
}
2826
27+
class Fuel {}
28+
2929
class V8Engine implements Engine {
30+
Fuel fuel;
31+
V8Engine(this.fuel);
32+
3033
go() {
3134
print('Vroom...');
3235
}
@@ -64,14 +67,17 @@ class ElectricCar {
6467
}
6568
6669
void main() {
67-
var injector = defaultInjector(modules: [new Module()
70+
var injector = new ModuleInjector(modules: [new Module()
6871
..bind(GenericCar)
6972
..bind(ElectricCar)
70-
..bind(Engine, toFactory: (i) => new V8Engine())
73+
..bind(Engine, toFactory: (fuel) => new V8Engine(fuel), inject: [Fuel])
7174
..bind(Engine, toImplementation: ElectricEngine, withAnnotation: Electric)
7275
]);
73-
injector.get(GenericCar).drive();
74-
injector.get(ElectricCar).drive();
76+
injector.get(GenericCar).drive(); // Vroom...
77+
injector.get(ElectricCar).drive(); // Hum...
7578
}
7679
```
7780

81+
## Contributing
82+
83+
Refer to the guidelines for [contributing to AngularDart](http://goo.gl/nrXVgm).
+3-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import 'package:benchmark_harness/benchmark_harness.dart';
2-
import 'package:di/dynamic_injector.dart';
2+
import 'package:di/src/reflector_dynamic.dart';
33

44
import 'injector_benchmark_common.dart';
55

6-
76
main() {
87
new InjectorBenchmark('DynamicInjectorBenchmark',
9-
(m) => new DynamicInjector(modules: m)).report();
10-
}
8+
new DynamicTypeFactories()).report();
9+
}

benchmark/injector_benchmark_common.dart

+54-19
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,43 @@ import 'package:di/di.dart';
66
int count = 0;
77

88
class InjectorBenchmark extends BenchmarkBase {
9-
var injectorFactory;
109
var module;
10+
var typeReflector;
11+
Key KEY_A;
12+
Key KEY_B;
13+
Key KEY_C;
14+
Key KEY_D;
15+
Key KEY_E;
1116

12-
InjectorBenchmark(name, this.injectorFactory) : super(name);
17+
InjectorBenchmark(name, this.typeReflector) : super(name);
1318

1419
void run() {
15-
Injector injector = injectorFactory([module]);
16-
injector.get(A);
17-
injector.get(B);
20+
Injector injector = new ModuleInjector([module]);
21+
injector.getByKey(KEY_A);
22+
injector.getByKey(KEY_B);
1823

19-
var childInjector = injector.createChild([module]);
20-
childInjector.get(A);
21-
childInjector.get(B);
24+
var childInjector = new ModuleInjector([module], injector);
25+
childInjector.getByKey(KEY_A);
26+
childInjector.getByKey(KEY_B);
2227
}
2328

2429
setup() {
25-
module = new Module()
26-
..type(A)
27-
..type(B)
28-
..type(C)
29-
..type(C, withAnnotation: AnnOne, implementedBy: COne )
30-
..type(D)
31-
..type(E)
32-
..type(E, withAnnotation: AnnTwo, implementedBy: ETwo )
33-
..type(F)
34-
..type(G);
30+
module = new Module.withReflector(typeReflector)
31+
..bind(A)
32+
..bind(B)
33+
..bind(C)
34+
..bind(C, withAnnotation: AnnOne, toImplementation: COne )
35+
..bind(D)
36+
..bind(E)
37+
..bind(E, withAnnotation: AnnTwo, toImplementation: ETwo )
38+
..bind(F)
39+
..bind(G);
40+
41+
KEY_A = new Key(A);
42+
KEY_B = new Key(B);
43+
KEY_C = new Key(C);
44+
KEY_D = new Key(D);
45+
KEY_E = new Key(E);
3546
}
3647

3748
teardown() {
@@ -96,7 +107,31 @@ class F {
96107
}
97108

98109
class G {
99-
G(@AnnTwo() E) {
110+
G(@AnnTwo() E e) {
100111
count++;
101112
}
102113
}
114+
115+
var typeFactories = {
116+
A: (a1, a2) => new A(a1, a2),
117+
B: (a1, a2) => new B(a1, a2),
118+
C: () => new C(),
119+
D: () => new D(),
120+
E: () => new E(),
121+
COne: () => new COne(),
122+
ETwo: () => new ETwo(),
123+
F: (a1, a2) => new F(a1, a2),
124+
G: (a1) => new G(a1),
125+
};
126+
127+
var paramKeys = {
128+
A: [new Key(B), new Key(C)],
129+
B: [new Key(D), new Key(E)],
130+
C: const [],
131+
D: const [],
132+
E: const [],
133+
COne: const [],
134+
ETwo: const [],
135+
F: [new Key(C, AnnOne), new Key(D)],
136+
G: [new Key(G, AnnTwo)],
137+
};

benchmark/instance_benchmark.dart

+5-12
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,22 @@
1-
import 'package:di/static_injector.dart';
1+
import 'package:di/di.dart';
2+
import 'package:di/src/reflector_static.dart';
23

34
import 'injector_benchmark_common.dart';
45

56
// tests the speed of cached getInstanceByKey requests
67
class InstanceBenchmark extends InjectorBenchmark{
7-
InstanceBenchmark(name, injectorFactory) : super(name, injectorFactory);
8+
InstanceBenchmark(name, typeReflector) : super(name, typeReflector);
89

910
void run(){
10-
Injector injector = injectorFactory([module]);
11+
Injector injector = new ModuleInjector([module]);
1112
for (var i = 0; i < 30; i++) {
1213
injector.get(A);
1314
}
1415
}
1516
}
1617

1718
main() {
18-
var typeFactories = {
19-
A: (f) => new A(f(B), f(C)),
20-
B: (f) => new B(f(D), f(E)),
21-
C: (f) => new C(),
22-
D: (f) => new D(),
23-
E: (f) => new E(),
24-
};
25-
2619
new InstanceBenchmark('InstanceBenchmark',
27-
(m) => new StaticInjector(modules: m, typeFactories: typeFactories)
20+
new GeneratedTypeFactories(typeFactories, paramKeys)
2821
).report();
2922
}

benchmark/large_benchmark.dart

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import 'package:benchmark_harness/benchmark_harness.dart';
2+
import 'package:di/di.dart';
3+
import 'package:di/src/reflector_static.dart';
4+
import 'generated_files/factories.dart';
5+
6+
import 'dart:math';
7+
8+
class LargeBenchmark extends BenchmarkBase {
9+
var injectorFactory;
10+
Injector rootInjector;
11+
Injector leafInjector;
12+
var leafKey;
13+
var rng = new Random();
14+
var numInjectors = 1;
15+
var allLeaves = [];
16+
17+
LargeBenchmark(name, this.injectorFactory) : super("Large" + name);
18+
19+
setup() {
20+
var rootModule = new Module()
21+
..bindByKey(key999)
22+
..bindByKey(key998)
23+
..bindByKey(key997)
24+
..bindByKey(key996)
25+
..bindByKey(key995);
26+
rootInjector = injectorFactory([rootModule]);
27+
28+
createChildren (injector, depth, width) {
29+
if (depth <= 0){
30+
allLeaves.add(injector);
31+
return;
32+
}
33+
for (var i=0; i<width; i++){
34+
var module = new Module();
35+
for (var j=0; j<5; j++){
36+
leafKey = allKeys[rng.nextInt(995)];
37+
module.bindByKey(leafKey);
38+
}
39+
leafInjector = injector.createChild([module]);
40+
numInjectors++;
41+
createChildren(leafInjector, depth-1, width);
42+
}
43+
}
44+
45+
createChildren(rootInjector, 5, 5);
46+
print("$numInjectors injectors created.");
47+
}
48+
}
49+
50+
class GetFromRoot extends LargeBenchmark {
51+
GetFromRoot() : super('FromRoot', (m) => new ModuleInjector(m));
52+
53+
run() {
54+
leafInjector.getByKey(key999);
55+
}
56+
}
57+
58+
class GetFromLeaf extends LargeBenchmark {
59+
GetFromLeaf() : super('FromLeaf', (m) => new ModuleInjector(m));
60+
61+
run() {
62+
leafInjector.getByKey(leafKey);
63+
}
64+
}
65+
66+
main() {
67+
Module.DEFAULT_REFLECTOR = new GeneratedTypeFactories(typeFactories, parameterKeys);
68+
new GetFromRoot().report();
69+
new GetFromLeaf().report();
70+
}

benchmark/module_benchmark.dart

+11-6
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,26 @@ import 'package:di/di.dart';
33

44
import 'injector_benchmark_common.dart';
55

6+
/**
7+
* tests the speed of looking up typeFactories and binding them to
8+
* a module. Mirroring time is not counted because DynamicTypeFactories
9+
* caches the results.
10+
*/
611
class ModuleBenchmark extends BenchmarkBase {
712
var injectorFactory;
813

914
ModuleBenchmark() : super('ModuleBenchmark');
1015

1116
void run() {
1217
var m = new Module()
13-
..type(A)
14-
..type(B)
15-
..type(C)
16-
..type(D)
17-
..type(E);
18+
..bind(A)
19+
..bind(B)
20+
..bind(C)
21+
..bind(D)
22+
..bind(E);
1823
}
1924
}
2025

2126
main() {
2227
new ModuleBenchmark().report();
23-
}
28+
}

0 commit comments

Comments
 (0)