diff options
Diffstat (limited to 'src/javax/inject/package-info.java')
-rw-r--r-- | src/javax/inject/package-info.java | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/javax/inject/package-info.java b/src/javax/inject/package-info.java new file mode 100644 index 0000000..5247410 --- /dev/null +++ b/src/javax/inject/package-info.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2009 The JSR-330 Expert Group + * + * 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. + */ + +/** + * This package specifies a means for obtaining objects in such a way as to + * maximize reusability, testability and maintainability compared to + * traditional approaches such as constructors, factories, and service + * locators (e.g., JNDI). This process, known as <i>dependency + * injection</i>, is beneficial to most nontrivial applications. + * + * <p>Many types depend on other types. For example, a <tt>Stopwatch</tt> might + * depend on a <tt>TimeSource</tt>. The types on which a type depends are + * known as its <i>dependencies</i>. The process of finding an instance of a + * dependency to use at run time is known as <i>resolving</i> the dependency. + * If no such instance can be found, the dependency is said to be + * <i>unsatisfied</i>, and the application is broken. + * + * <p>In the absence of dependency injection, an object can resolve its + * dependencies in a few ways. It can invoke a constructor, hard-wiring an + * object directly to its dependency's implementation and life cycle: + * + * <pre> class Stopwatch { + * final TimeSource timeSource; + * Stopwatch () { + * timeSource = <b>new AtomicClock(...)</b>; + * } + * void start() { ... } + * long stop() { ... } + * }</pre> + * + * <p>If more flexibility is needed, the object can call out to a factory or + * service locator: + * + * <pre> class Stopwatch { + * final TimeSource timeSource; + * Stopwatch () { + * timeSource = <b>DefaultTimeSource.getInstance()</b>; + * } + * void start() { ... } + * long stop() { ... } + * }</pre> + * + * <p>In deciding between these traditional approaches to dependency + * resolution, a programmer must make trade-offs. Constructors are more + * concise but restrictive. Factories decouple the client and implementation + * to some extent but require boilerplate code. Service locators decouple even + * further but reduce compile time type safety. All three approaches inhibit + * unit testing. For example, if the programmer uses a factory, each test + * against code that depends on the factory will have to mock out the factory + * and remember to clean up after itself or else risk side effects: + * + * <pre> void testStopwatch() { + * <b>TimeSource original = DefaultTimeSource.getInstance(); + * DefaultTimeSource.setInstance(new MockTimeSource()); + * try {</b> + * // Now, we can actually test Stopwatch. + * Stopwatch sw = new Stopwatch(); + * ... + * <b>} finally { + * DefaultTimeSource.setInstance(original); + * }</b> + * }</pre> + * + * <p>In practice, supporting this ability to mock out a factory results in + * even more boilerplate code. Tests that mock out and clean up after multiple + * dependencies quickly get out of hand. To make matters worse, a programmer + * must predict accurately how much flexibility will be needed in the future + * or else suffer the consequences. If a programmer initially elects to use a + * constructor but later decides that more flexibility is required, the + * programmer must replace every call to the constructor. If the programmer + * errs on the side of caution and write factories up front, it may result in + * a lot of unnecessary boilerplate code, adding noise, complexity, and + * error-proneness. + * + * <p><i>Dependency injection</i> addresses all of these issues. Instead of + * the programmer calling a constructor or factory, a tool called a + * <i>dependency injector</i> passes dependencies to objects: + * + * <pre> class Stopwatch { + * final TimeSource timeSource; + * <b>@Inject Stopwatch(TimeSource timeSource)</b> { + * this.timeSource = timeSource; + * } + * void start() { ... } + * long stop() { ... } + * }</pre> + * + * <p>The injector further passes dependencies to other dependencies until it + * constructs the entire object graph. For example, suppose the programmer + * asked an injector to create a <tt>StopwatchWidget</tt> instance: + * + * <pre> /** GUI for a Stopwatch */ + * class StopwatchWidget { + * @Inject StopwatchWidget(Stopwatch sw) { ... } + * ... + * }</pre> + * + * <p>The injector might: + * <ol> + * <li>Find a <tt>TimeSource</tt> + * <li>Construct a <tt>Stopwatch</tt> with the <tt>TimeSource</tt> + * <li>Construct a <tt>StopwatchWidget</tt> with the <tt>Stopwatch</tt> + * </ol> + * + * <p>This leaves the programmer's code clean, flexible, and relatively free + * of dependency-related infrastructure. + * + * <p>In unit tests, the programmer can now construct objects directly + * (without an injector) and pass in mock dependencies. The programmer no + * longer needs to set up and tear down factories or service locators in each + * test. This greatly simplifies our unit test: + * + * <pre> void testStopwatch() { + * Stopwatch sw = new Stopwatch(new MockTimeSource()); + * ... + * }</pre> + * + * <p>The total decrease in unit-test complexity is proportional to the + * product of the number of unit tests and the number of dependencies. + * + * <p><b>This package provides dependency injection annotations that enable + * portable classes</b>, but it leaves external dependency configuration up to + * the injector implementation. Programmers annotate constructors, methods, + * and fields to advertise their injectability (constructor injection is + * demonstrated in the examples above). A dependency injector identifies a + * class's dependencies by inspecting these annotations, and injects the + * dependencies at run time. Moreover, the injector can verify that all + * dependencies have been satisfied at <i>build time</i>. A service locator, + * by contrast, cannot detect unsatisfied dependencies until run time. + * + * <p>Injector implementations can take many forms. An injector could + * configure itself using XML, annotations, a DSL (domain-specific language), + * or even plain Java code. An injector could rely on reflection or code + * generation. An injector that uses compile-time code generation may not even + * have its own run time representation. Other injectors may not be able to + * generate code at all, neither at compile nor run time. A "container", for + * some definition, can be an injector, but this package specification aims to + * minimize restrictions on injector implementations. + * + * @see javax.inject.Inject @Inject + */ +package javax.inject; |