forked from square/dagger
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
515 lines (399 loc) · 25.8 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dagger</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A fast dependency injector for Android and Java">
<link href="static/bootstrap-combined.min.css" rel="stylesheet">
<link href="static/app.css" rel="stylesheet">
<link href="static/app-theme.css" rel="stylesheet">
<link href="http://fonts.googleapis.com/css?family=Roboto:400,300italic,100,100italic,300" rel="stylesheet" type="text/css">
<!--[if lt IE 9]><script src="static/html5shiv.min.js"></script><![endif]-->
</head>
<body data-target=".content-nav">
<header>
<div class="container">
<div class="row">
<div class="span5">
<h1>Dagger</h1>
</div>
<div class="span7">
<menu>
<ul>
<li><a href="#download" class="menu download">Download <span class="version-tag">Latest</span></a></li>
<li><a href="http://github.com/square/dagger" data-title="View GitHub Project" class="menu github"><img src="static/icon-github.png" alt="GitHub"/></a></li>
<li><a href="http://square.github.io/" data-title="Square Open Source Portal" class="menu square"><img src="static/icon-square.png" alt="Square"/></a></li>
</ul>
</menu>
</div>
</div>
</header>
<section id="subtitle">
<div class="container">
<div class="row">
<div class="span12">
<h2>A fast <strong>dependency injector</strong> for Android and Java</h2>
</div>
</div>
</div>
</section>
<section id="body">
<div class="container">
<div class="row">
<div class="span9">
<h3 id="introduction">Introduction</h3>
<p>The best classes in any application are the ones that do stuff: the <code>BarcodeDecoder</code>, the <code>KoopaPhysicsEngine</code>, and the <code>AudioStreamer</code>. These classes have dependencies; perhaps a <code>BarcodeCameraFinder</code>, <code>DefaultPhysicsEngine</code>, and an <code>HttpStreamer</code>.</p>
<p>To contrast, the worst classes in any application are the ones that take up space without doing much at all: the <code>BarcodeDecoderFactory</code>, the <code>CameraServiceLoader</code>, and the <code>MutableContextWrapper</code>. These classes are the clumsy duct tape that wires the interesting stuff together.</p>
<p>Dagger is a replacement for these <code>FactoryFactory</code> classes. It allows you to focus on the interesting classes. Declare dependencies, specify how to satisfy them, and ship your app.</p>
<p>By building on standard <a href="http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/package-summary.html">javax.inject</a> annotations (JSR-330), each class is <strong>easy to test</strong>. You don't need a bunch of boilerplate just to swap the <code>RpcCreditCardService</code> out for a <code>FakeCreditCardService</code>.</p>
<p>Dependency injection isn't just for testing. It also makes it easy to create <strong>reusable, interchangeable modules</strong>. You can share the same <code>AuthenticationModule</code> across all of your apps. And you can run <code>DevLoggingModule</code> during development and <code>ProdLoggingModule</code> in production to get the right behavior in each situation.</p>
<p>For more information, <a href="http://www.infoq.com/presentations/Dagger">watch an introductory talk</a> by Jesse Wilson at QCon 2012.</p>
<h3 id="using">Using Dagger</h3>
<p>We'll demonstrate dependency injection and Dagger by building a coffee maker. For complete sample code that you can compile and run, see Dagger's <a href="https://github.com/square/dagger/tree/master/examples/simple/src/main/java/coffee">coffee example</a>.</p>
<h4>Declaring Dependencies</h4>
<p>Dagger constructs instances of your application classes and satisfies their dependencies. It uses the <code>javax.inject.Inject</code> annotation to identify which constructors and fields it is interested in.</p>
<p>Use <code>@Inject</code> to annotate the constructor that Dagger should use to create instances of a class. When a new instance is requested, Dagger will obtain the required parameters values and invoke this constructor.</p>
<pre class="prettyprint">class Thermosiphon implements Pump {
private final Heater heater;
@Inject
Thermosiphon(Heater heater) {
this.heater = heater;
}
...
}</pre>
<p>Dagger can inject fields directly. In this example it obtains a <code>Heater</code> instance for the <code>heater</code> field and a <code>Pump</code> instance for the <code>pump</code> field.</p>
<pre class="prettyprint">class CoffeeMaker {
@Inject Heater heater;
@Inject Pump pump;
...
}</pre>
<p>If your class has <code>@Inject</code>-annotated fields but no <code>@Inject</code>-annotated constructor, Dagger will use a no-argument constructor if it exists. Classes that lack <code>@Inject</code> annotations cannot be constructed by Dagger.</p>
<p>Dagger does not support method injection.</p>
<h4>Satisfying Dependencies</h4>
<p>By default, Dagger satisfies each dependency by constructing an instance of the requested type as described above. When you request a <code>CoffeeMaker</code>, it'll obtain one by calling <code>new CoffeeMaker()</code> and setting its injectable fields.</p>
<p>But <code>@Inject</code> doesn't work everywhere:</p>
<ul>
<li>Interfaces can't be constructed.</li>
<li>Third-party classes can't be annotated.</li>
<li>Configurable objects must be configured!</li>
</ul>
<p>For these cases where <code>@Inject</code> is insufficient or awkward, use an <code>@Provides</code>-annotated method to satisfy a dependency. The method's return type defines which dependency it satisfies.</p>
<p>For example, <code>provideHeater()</code> is invoked whenever a <code>Heater</code> is required:</p>
<pre class="prettyprint">@Provides Heater provideHeater() {
return new ElectricHeater();
}</pre>
<p>It's possible for <code>@Provides</code> methods to have dependencies of their own. This one returns a <code>Thermosiphon</code> whenever a <code>Pump</code> is required:</p>
<pre class="prettyprint">@Provides Pump providePump(Thermosiphon pump) {
return pump;
}</pre>
<p>All <code>@Provides</code> methods must belong to a module. These are just classes that have an <code>@Module</code> annotation.</p>
<pre class="prettyprint">@Module
class DripCoffeeModule {
@Provides Heater provideHeater() {
return new ElectricHeater();
}
@Provides Pump providePump(Thermosiphon pump) {
return pump;
}
}</pre>
<p>By convention, <code>@Provides</code> methods are named with a <code>provide</code> prefix and module classes are named with a <code>Module</code> suffix.</p>
<h4>Building the Graph</h4>
<p>The <code>@Inject</code> and <code>@Provides</code>-annotated classes form a graph of objects, linked by their dependencies. Obtain this graph by calling <code>ObjectGraph.create()</code>, which accepts one or more modules:</p>
<pre class="prettyprint">ObjectGraph objectGraph = ObjectGraph.create(new DripCoffeeModule());</pre>
<p>In order to put the graph to use we need to <strong>bootstrap injection</strong>. This usually requires injecting the main class of a command line app, or the activity classes of an Android app. In our coffee example, the <code>CoffeeApp</code> class is used to start dependency injection. We ask the graph to provide an injected instance of the class:</p>
<pre class="prettyprint">class CoffeeApp implements Runnable {
@Inject CoffeeMaker coffeeMaker;
@Override public void run() {
coffeeMaker.brew();
}
public static void main(String[] args) {
ObjectGraph objectGraph = ObjectGraph.create(new DripCoffeeModule());
CoffeeApp coffeeApp = objectGraph.get(CoffeeApp.class);
...
}
}</pre>
<p>The only thing that's missing is that the injectable class <code>CoffeeApp</code> isn't known by the graph. We need to explicitly register it as an injected type in the <code>@Module</code> annotation.</p>
<pre class="prettyprint">@Module(
injects = CoffeeApp.class
)
class DripCoffeeModule {
...
}</pre>
<p>The <code>injects</code> option enables the complete graph to be validated <strong>at compile time</strong>. Detecting problems early speeds up development and takes some of the danger out of refactoring.</p>
<p>Now that the graph is constructed and the root object is injected, we run our coffee maker app. Fun.</p>
<pre>$ java -cp ... coffee.CoffeeApp
~ ~ ~ heating ~ ~ ~
=> => pumping => =>
[_]P coffee! [_]P</pre>
<h4>Singletons</h4>
<p>Annotate an <code>@Provides</code> method or injectable class with <code>@Singleton</code>. The graph will use a single instance of the value for all of its clients.</p>
<pre class="prettyprint">@Provides @Singleton Heater provideHeater() {
return new ElectricHeater();
}</pre>
<p>The <code>@Singleton</code> annotation on an injectable class also serves as documentation. It reminds potential maintainers that this class may be shared by multiple threads.</p>
<pre class="prettyprint">@Singleton
class CoffeeMaker {
...
}</pre>
<h4>Lazy injections</h4>
<p>Sometimes you need an object to be instantiated lazily. For any binding <code>T</code>, you can create a <code>Lazy<T></code> which defers instantiation until the first call to <code>Lazy<T></code>'s <code>get()</code> method. If <code>T</code> is a singleton, then <code>Lazy<T></code> will be the same instance for all injections within the <code>ObjectGraph</code>. Otherwise, each injection site will get its own <code>Lazy<T></code> instance. Regardless, subsequent calls to any given instance of <code>Lazy<T></code> will return the same underlying instance of <code>T</code>.</p>
<pre class="prettyprint">class GridingCoffeeMaker {
@Inject Lazy<Grinder> lazyGrinder;
public void brew() {
while (needsGrinding()) {
// Grinder created once on first call to .get() and cached.
lazyGrinder.get().grind();
}
}
}</pre>
<h4>Provider injections</h4>
<p>Sometimes you need multiple instances to be returned instead of just injecting a single value. While you have several options (Factories, Builders, etc.) one option is to inject a <code>Provider<T></code> instead of just <code>T</code>. A <code>Provider<T></code> creates a new instance of <code>T</code> each time <code>.get()</code> is called.</p>
<pre class="prettyprint">class BigCoffeeMaker {
@Inject Provider<Filter> filterProvider;
public void brew(int numberOfPots) {
...
for (int p = 0; p < numberOfPots; p++) {
maker.addFilter(filterProvider.get()); //new filter every time.
maker.addCoffee(...);
maker.percolate();
...
}
}
}</pre>
<p><span class="label">Note:</span><em> Injecting <code>Provider<T></code> has the possibility of creating confusing code, and may be a design smell of mis-scoped or mis-structured objects in your graph. Often you will want to use a <code>Factory<T></code> or a <code>Lazy<T></code> or re-organize the lifetimes and structure of your code to be able to just inject a <code>T</code>. Injecting <code>Provider<T></code> can, however, be a life saver in some cases. A common use is when you must use a legacy architecture that doesn't line up with your object's natural lifetimes (e.g. servlets are singletons by design, but only are valid in the context of request-specfic data).</em></p>
<h4>Qualifiers</h4>
<p>Sometimes the type alone is insufficient to identify a dependency. For example, a sophisticated coffee maker app may want separate heaters for the water and the hot plate.</p>
<p>In this case, we add a <strong>qualifier annotation</strong>. This is any annotation that itself has a <code>@Qualifier</code> annotation. Here's the declaration of <code>@Named</code>, a qualifier annotation included in <code>javax.inject</code>:</p>
<pre class="prettyprint">@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {
String value() default "";
}</pre>
<p>You can create your own qualifier annotations, or just use <code>@Named</code>. Apply qualifiers by annotating the field or parameter of interest. The type and qualifier annotation will both be used to identify the dependency.</p>
<pre class="prettyprint">class ExpensiveCoffeeMaker {
@Inject @Named("water") Heater waterHeater;
@Inject @Named("hot plate") Heater hotPlateHeater;
...
}</pre>
<p>Supply qualified values by annotating the corresponding <code>@Provides</code> method.</p>
<pre class="prettyprint">@Provides @Named("hot plate") Heater provideHotPlateHeater() {
return new ElectricHeater(70);
}
@Provides @Named("water") Heater provideWaterHeater() {
return new ElectricHeater(93);
}</pre>
<p>Dependencies may not have multiple qualifier annotations.</p>
<h4>Static Injection</h4>
<p><span class="label label-important">Warning:</span> This feature should be used sparingly because static dependencies are difficult to test and reuse.</p>
<p>Dagger can inject static fields. Classes that declare static fields with <code>@Inject</code> annotations must be listed as <code>staticInjections</code> in a module annotation.</p>
<pre class="prettyprint">@Module(
staticInjections = LegacyCoffeeUtils.class
)
class LegacyModule {
}</pre>
<p>Use <code>ObjectGraph.injectStatics()</code> to populate these static fields with their injected values:</p>
<pre class="prettyprint">ObjectGraph objectGraph = ObjectGraph.create(new LegacyModule());
objectGraph.injectStatics();</pre>
<p><span class="label">Note:</span> <em>Static injection only operates for modules in the immediate graph. If you call <code>injectStatics()</code> on a graph created from a call to <code>plus()</code>, static injections on modules in the extended graph will not be performed.</em></p>
<h4>Compile-time Validation</h4>
<p>Dagger includes an <a href="http://docs.oracle.com/javase/6/docs/api/javax/annotation/processing/package-summary.html">annotation processor</a> that validates modules and injections. This processor is strict and will cause a compiler error if any bindings are invalid or incomplete. For example, this module is missing a binding for <code>Executor</code>:</p>
<pre class="prettyprint">@Module
class DripCoffeeModule {
@Provides Heater provideHeater(Executor executor) {
return new CpuHeater(executor);
}
}</pre>
<p>When compiling it, <code>javac</code> rejects the missing binding:</p>
<pre>[ERROR] COMPILATION ERROR :
[ERROR] error: No binding for java.util.concurrent.Executor
required by provideHeater(java.util.concurrent.Executor)</pre>
<p>Fix the problem either by adding an <code>@Provides</code>-annotated method for <code>Executor</code>, or by marking the module as incomplete. Incomplete modules are permitted to have missing dependencies.</p>
<pre class="prettyprint">@Module(complete = false)
class DripCoffeeModule {
@Provides Heater provideHeater(Executor executor) {
return new CpuHeater(executor);
}
}</pre>
<p>Modules which provide types that are unused by the listed injects classes will also trigger an error.</p>
<pre class="prettyprint">@Module(injects = Example.class)
class DripCoffeeModule {
@Provides Heater provideHeater() {
return new ElectricHeater();
}
@Provides Chiller provideChiller() {
return new ElectricChiller();
}
}</pre>
<p>Because the <code>Example</code> inject in the module only uses the <code>Heater</code>, <code>javac</code> rejects the unused binding:</p>
<pre>[ERROR] COMPILATION ERROR:
[ERROR]: Graph validation failed: You have these unused @Provider methods:
1. coffee.DripCoffeeModule.provideChiller()
Set library=true in your module to disable this check.</pre>
<p>If your module's bindings will be used outside of the listed injects then mark the module as a library.</p>
<pre class="prettyprint">@Module(
injects = Example.class,
library = true
)
class DripCoffeeModule {
@Provides Heater provideHeater() {
return new ElectricHeater();
}
@Provides Chiller provideChiller() {
return new ElectricChiller();
}
}</pre>
<p>To get the most out of compile-time validation, create a module that includes all of your application's modules. The annotation processor will detect problems across the modules and report them.</p>
<pre class="prettyprint">@Module(
includes = {
DripCoffeeModule.class,
ExecutorModule.class
}
)
public class CoffeeAppModule {
}</pre>
<p>The annotation processor is enabled automatically when you include Dagger's jar file on your compile classpath.</p>
<h4>Compile-time Code Generation</h4>
<p>Dagger's annotation processor may also generate source files with names like <code>CoffeeMaker$InjectAdapter.java</code> or <code>DripCoffeeModule$ModuleAdapter</code>. These files are Dagger implementation details. You shouldn't need to use them directly, though they can be handy when step-debugging through an injection.</p>
<h4>Module overrides</h4>
<p>Dagger will fail with an error if there are multiple competing <code>@Provides</code> methods for the same dependency. But sometimes it's necessary to replace production code with a substitute for development or testing. Using <code>overrides = true</code> in a module annotation lets you take precedence over the bindings of other modules.</p>
<p>This JUnit test overrides <code>DripCoffeeModule</code>'s binding for <code>Heater</code> with a mock object from <a href="http://mockito.googlecode.com/">Mockito</a>. The mock gets injected into the <code>CoffeeMaker</code> and also into the test.</p>
<pre class="prettyprint">public class CoffeeMakerTest {
@Inject CoffeeMaker coffeeMaker;
@Inject Heater heater;
@Before public void setUp() {
ObjectGraph.create(new TestModule()).inject(this);
}
@Module(
includes = DripCoffeeModule.class,
injects = CoffeeMakerTest.class,
overrides = true
)
static class TestModule {
@Provides @Singleton Heater provideHeater() {
return Mockito.mock(Heater.class);
}
}
@Test public void testHeaterIsTurnedOnAndThenOff() {
Mockito.when(heater.isHot()).thenReturn(true);
coffeeMaker.brew();
Mockito.verify(heater, Mockito.times(1)).on();
Mockito.verify(heater, Mockito.times(1)).off();
}
}</pre>
<p>Overrides are best suited for small variations on the application:</p>
<ul>
<li>Replacing the real implementation with a mock for unit tests.</li>
<li>Replacing LDAP authentication with fake authentication for development.</li>
</ul>
<p>For more substantial variations it's often simpler to use a different combination of modules.</p>
<h3 id="download">Download</h3>
<p><a href="http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.dagger&a=dagger&v=LATEST" class="dl core-version-href">↓ <span class="version-tag">Latest</span> JAR</a> <a href="http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.dagger&a=dagger-compiler&v=LATEST" class="dl compiler-version-href">↓ <span class="version-tag">Latest</span> Compiler JAR</a></p>
<p>You will need to include the Dagger JAR in your application's runtime. In order to activate code generation you will need to include the compiler JAR in your build at compile time.</p>
<p>The source code to the Dagger, its samples, and this website is <a href="http://github.com/square/dagger">available on GitHub</a>.</p>
<h4>Maven</h4>
<pre class="prettyprint"><dependency>
<groupId>com.squareup.dagger</groupId>
<artifactId>dagger</artifactId>
<version><span class="version pln"><em>(insert latest version)</em></span></version>
</dependency>
<dependency>
<groupId>com.squareup.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version><span class="version pln"><em>(insert latest version)</em></span></version>
<optional>true</optional>
</dependency></pre>
<h3 id="upgrading">Upgrading from Guice</h3>
<p>Some notable Guice features that Dagger doesn't support:</p>
<ul>
<li>Injecting <code>final</code> fields and <code>private</code> members. For best performance Dagger generates code. Work around this by using constructor injection.</li>
<li>Eager singletons. Work around this by creating an <code>EagerSingletons</code> class that declares static fields for each eager singleton.</li>
<li>Method injection.</li>
<li>Classes that lack <code>@Inject</code> annotations cannot be constructed by Dagger, even if they have a no-argument constructor.</li>
</ul>
<h3 id="contributing">Contributing</h3>
<p>If you would like to contribute code you can do so through GitHub by forking the repository and sending a pull request.</p>
<p>When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. Please also make sure your code compiles by running <code>mvn clean verify</code>.</p>
<p>Before your code can be accepted into the project you must also sign the <a href="http://squ.re/sign-the-cla">Individual Contributor License Agreement (CLA)</a>.</p>
<h3 id="license">License</h3>
<pre>Copyright 2013 Square, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.</pre>
</div>
<div class="span3">
<div class="content-nav" data-spy="affix" data-offset-top="80">
<ul class="nav nav-tabs nav-stacked primary">
<li><a href="#introduction">Introduction</a></li>
<li><a href="#using">Using Dagger</a></li>
<li><a href="#download">Download</a></li>
<li><a href="#upgrading">Upgrading from Guice</a></li>
<li><a href="#contributing">Contributing</a></li>
<li><a href="#license">License</a></li>
</ul>
<ul class="nav nav-pills nav-stacked secondary">
<li><a href="javadoc/index.html">Javadoc</a></li>
<li><a href="https://groups.google.com/forum/#!forum/dagger-discuss">dagger-discuss@</a></li>
<li><a href="http://stackoverflow.com/questions/tagged/dagger?sort=active">StackOverflow</a></li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="span12 logo">
<a href="https://squareup.com"><img src="static/logo-square.png" alt="Square, Inc."/></a>
</div>
</div>
</div>
</section>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="static/bootstrap.min.js"></script>
<script src="static/jquery.smooth-scroll.min.js"></script>
<script src="static/jquery-maven-artifact.min.js"></script>
<script src="static/prettify.js"></script>
<script type="text/javascript">
$(function() {
// Syntax highlight code blocks.
prettyPrint();
// Spy on scroll position for real-time updating of current section.
$('body').scrollspy();
// Use smooth-scroll for internal links.
$('a').smoothScroll();
// Enable tooltips on the header nav image items.
$('.menu').tooltip({
placement: 'bottom',
trigger: 'hover',
container: 'body',
delay: {
show: 500,
hide: 0
}
});
// Look up the latest version of the library.
$.fn.artifactVersion('com.squareup.dagger', 'dagger', function(version, url) {
$('.version').text(version);
$('.version-tag').text('v' + version);
$('.core-version-href').attr('href', url);
});
$.fn.artifactVersion('com.squareup.dagger', 'dagger-compiler', function(version, url) {
$('.compiler-version-href').attr('href', url);
});
});
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-40704740-3']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>