Table Of ContentDependency
Injection
D S G
ESIGN PATTERNS USING PRING AND UICE
DHANJI R. PRASANNA
MANNING
Greenwich
(74° w. long.)
For online information and ordering of this and other Manning books, please visit
www.manning.com. The publisher offers discounts on this book when ordered in quantity.
For more information, please contact
Special Sales Department
Manning Publications Co.
Sound View Court 3B fax: (609) 877-8256
Greenwich, CT 06830 email: orders@manning.com
©2009 by Manning Publications Co. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in
any form or by means electronic, mechanical, photocopying, or otherwise, without prior written
permission of the publisher.
Many of the designations used by manufacturers and sellers to distinguish their products are
claimed as trademarks. Where those designations appear in the book, and Manning
Publications was aware of a trademark claim, the designations have been printed in initial caps
or all caps.
Recognizing the importance of preserving what has been written, it is Manning’s policy to have
the books we publish printed on acid-free paper, and we exert our best efforts to that end.
Recognizing also our responsibility to conserve the resources of our planet, Manning books are
printed on paper that is at least 15% recycled and processed without the use of elemental chlorine.
Development Editor: Tom Cirtin
Manning Publications Co. Copyeditor: Linda Recktenwald
Sound View Court 3B Typesetter: Gordan Salinovic
Greenwich, CT 06830 Cover designer: Leslie Haimes
ISBN 978-1-933988-55-9
Printed in the United States of America
1 2 3 4 5 6 7 8 9 10 – MAL – 14 13 12 11 10 09
brief contents
1 ■ Dependency injection: what’s all the hype? 1
2 ■ Time for injection 21
3 ■ Investigating DI 54
4 ■ Building modular applications 99
5 ■ Scope: a fresh breath of state 123
6 ■ More use cases in scoping 156
7 ■ From birth to death: object lifecycle 186
8 ■ Managing an object’s behavior 210
9 ■ Best practices in code design 240
10 ■ Integrating with third-party frameworks 266
11 ■ Dependency injection in action! 289
vii
contents
preface xv
acknowledgments xvii
about this book xix
about the cover illustration xxii
1 Dependency injection: what’s all the hype? 1
1.1 Every solution needs a problem 2
Seeing objects as services 2
1.2 Pre-DI solutions 4
Construction by hand 5 ■ The Factory pattern 7 ■ The Service
Locator pattern 12
1.3 Embracing dependency injection 13
The Hollywood Principle 13 ■ Inversion of Control vs. dependency
injection 15
1.4 Dependency injection in the real world 17
Java 17 ■ DI in other languages and libraries 19
1.5 Summary 19
2 Time for injection 21
2.1 Bootstrapping the injector 22
2.2 Constructing objects with dependency injection 23
ix
x CONTENTS
2.3 Metadata and injector configuration 26
XML injection in Spring 27 ■ From XML to in-code configuration 30
Injection in PicoContainer 31 ■ Revisiting Spring and autowiring 34
2.4 Identifying dependencies for injection 36
Identifying by string keys 37 ■ Limitations of string keys 42
Identifying by type 44 ■ Limitations of identifying by type 46
Combinatorial keys: a comprehensive solution 47
2.5 Separating infrastructure and application logic 51
2.6 Summary 52
3 Investigating DI 54
3.1 Injection idioms 55
Constructor injection 55 ■ Setter injection 56 ■ Interface injection 60
Method decoration (or AOP injection) 62
3.2 Choosing an injection idiom 65
Constructor vs. setter injection 66 ■ The constructor pyramid problem 69
The circular reference problem 71 ■ The in-construction problem 75
Constructor injection and object validity 78
3.3 Not all at once: partial injection 81
The reinjection problem 81 ■ Reinjection with the Provider pattern 82
The contextual injection problem 84 ■ Contextual injection with the
Assisted Injection pattern 86 ■ Flexible partial injection with the Builder
pattern 88
3.4 Injecting objects in sealed code 92
Injecting with externalized metadata 93 ■ Using the Adapter pattern 95
3.5 Summary 96
4 Building modular applications 99
4.1 Understanding the role of an object 100
4.2 Separation of concerns (my pants are too tight!) 101
Perils of tight coupling 102 ■ Refactoring impacts of tight coupling
105 ■ Programming to contract 108 ■ Loose coupling with
dependency injection 111
4.3 Testing components 112
Out-of-container (unit) testing 113 ■ I really need my dependencies! 114
More on mocking dependencies 115 ■ Integration testing 116
4.4 Different deployment profiles 118
Rebinding dependencies 118 ■ Mutability with the Adapter pattern 119
4.5 Summary 121
CONTENTS xi
5 Scope: a fresh breath of state 123
5.1 What is scope? 124
5.2 The no scope (or default scope) 125
5.3 The singleton scope 128
Singletons in practice 131 ■ The singleton anti-pattern 135
5.4 Domain-specific scopes: the web 139
HTTP request scope 141 ■ HTTP session scope 149
5.5 Summary 154
6 More use cases in scoping 156
6.1 Defining a custom scope 157
A quick primer on transactions 157 ■ Creating a custom transaction
scope 158 ■ A custom scope in Guice 160 ■ A custom scope in
Spring 164
6.2 Pitfalls and corner cases in scoping 166
Singletons must be thread-safe 167 ■ Perils of scope-widening injection 169
6.3 Leveraging the power of scopes 180
Cache scope 181 ■ Grid scope 181 ■ Transparent grid computing
with DI 183
6.4 Summary 184
7 From birth to death: object lifecycle 186
7.1 Significant events in the life of objects 187
Object creation 187 ■ Object destruction (or finalization) 189
7.2 One size doesn’t fit all (domain-specific lifecycle) 191
Contrasting lifecycle scenarios: servlets vs. database connections 191 ■ The
Destructor anti-pattern 196 ■ Using Java’s Closeable interface 197
7.3 A real-world lifecycle scenario: stateful EJBs 198
7.4 Lifecycle and lazy instantiation 201
7.5 Customizing lifecycle with postprocessing 202
7.6 Customizing lifecycle with multicasting 205
7.7 Summary 207
8 Managing an object’s behavior 210
8.1 Intercepting methods and AOP 211
A tracing interceptor with Guice 212 ■ A tracing interceptor with Spring 214
How proxying works 216 ■ Too much advice can be dangerous! 219
xii CONTENTS
8.2 Enterprise use cases for interception 221
Transactional methods with warp-persist 222 ■ Securing methods
with Spring Security 224
8.3 Pitfalls and assumptions about interception and proxying 228
Sameness tests are unreliable 228 ■ Static methods cannot be
intercepted 230 ■ Neither can private methods 231 ■ And certainly
not final methods! 233 ■ Fields are off limits 234 ■ Unit tests and
interception 236
8.4 Summary 238
9 Best practices in code design 240
9.1 Objects and visibility 241
Safe publication 244 ■ Safe wiring 245
9.2 Objects and design 247
On data and services 247 ■ On better encapsulation 252
9.3 Objects and concurrency 257
More on mutability 258 ■ Synchronization vs. concurrency 261
9.4 Summary 264
10 Integrating with third-party frameworks 266
10.1 Fragmentation of DI solutions 267
10.2 Lessons for framework designers 270
Rigid configuration anti-patterns 271 ■ Black box anti-patterns 276
10.3 Programmatic configuration to the rescue 280
Case study: JSR-303 280
10.4 Summary 286
11 Dependency injection in action! 289
11.1 Crosstalk: a Twitter clone! 290
Crosstalk’s requirements 290
11.2 Setting up the application 290
11.3 Configuring Google Sitebricks 294
11.4 Crosstalk’s modularity and service coupling 295
11.5 The presentation layer 296
The HomePage template 298 ■ The Tweet domain object 301
Users and sessions 302 ■ Logging in and out 304
CONTENTS xiii
11.6 The persistence layer 308
Configuring the persistence layer 310
11.7 The security layer 311
11.8 Tying up to the web lifecycle 312
11.9 Finally: up and running! 313
11.10 Summary 314
appendix A The Butterfly Container 315
appendix B SmartyPants for Adobe Flex 320
index 323
preface
The reasonable man adapts himself to the world; the unreasonable one persists in trying
to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
—George Bernard Shaw
So, novice-expert-aficionado-learner, welcome to our dependency injection theme
park! We’ll begin this tour of dependency injection at the gate: by first defining the
problem it solves.
The tour will then proceed down the streams of specific implementations and pop-
ular technologies, examining quick solutions in such frameworks as Guice, Spring,
and PicoContainer, among others. A long break will follow for the purpose of theoret-
ical nourishment, where we shall discuss the foundational idioms behind dependency
injection, its core viral ideology, its types and practices.
Then, we’ll peruse the hall of curiosities where we consider such peculiar notions
as objects with managed state, lifecycle, and modularity and examine their curious
aspectual behaviors.
In turn, we’ll descend into the caverns of pitfalls, nuances, and corner cases that
ought to titillate and horrify the strongest of constitutions; for when you cross these
lines you can expect the demons of class loading, dynamic proxying, and unintended
encapsulation to rear their ugly heads, only to be shown up by even greater challenges
of concurrency.
We’ll make a round about the marvelous gilded architectures of enterprise appli-
cations, casting a purposeful eye at their grandeur, which is composed of modular,
xv
xvi PREFACE
remote-able service models that separate cleanly between compartments of the enter-
prise—particularly those nefarious tiers, web and business.
These will leave us with a meditation on the big picture—how we can marry these
elegant idioms of dependency injection with their many suitors: applications, third-
party libraries, and frameworks.
Finally, dear tourist, you will be presented with a purposed comparison of popular
dependency injection frameworks, gauging their performance, features, safety, and
rigor (as a functioning example in chapter 11).
The theme park metaphor aside, I have attempted to structure this book as a jour-
ney. While the ideas and engineering patterns explored in this book do not refer to a
particular language, many of the examples will be in Java. The frameworks we explore
will primarily be well-known Java libraries that are widely in use.
A basic understanding of Java (or C#) is preferable; however, for you to get the
best out of this book I also recommend familiarity with the principles of object-
oriented programming (particularly encapsulation, polymorphism, and inheritance).