javax.inject.package-info Maven / Gradle / Ivy
/*
* 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 org.testifyproject.testifyprojectpliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org.testifyproject/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 org.testifyproject.testifyprojectpared to
* traditional approaches such as constructors, factories, and service
* locators (e.g., JNDI). This process, known as org.testifyproject.testifyprojectpendency
* injection, is beneficial to most nontrivial applications.
*
* Many types org.testifyproject.testifyprojectpend on other types. For example, a Stopwatch might
* org.testifyproject.testifyprojectpend on a TimeSource. The types on which a type org.testifyproject.testifyprojectpends are
* known as its org.testifyproject.testifyprojectpendencies. The process of finding an instance of a
* org.testifyproject.testifyprojectpendency to use at run time is known as resolving the org.testifyproject.testifyprojectpendency.
* If no such instance can be found, the org.testifyproject.testifyprojectpendency is said to be
* unsatisfied, and the application is broken.
*
*
In the absence of org.testifyproject.testifyprojectpendency injection, an object can resolve its
* org.testifyproject.testifyprojectpendencies in a few ways. It can invoke a constructor, hard-wiring an
* object directly to its org.testifyproject.testifyprojectpendency's implementation and life cycle:
*
*
class Stopwatch {
* final TimeSource timeSource;
* Stopwatch () {
* timeSource = new AtomicClock(...);
* }
* void start() { ... }
* long stop() { ... }
* }
*
* If more flexibility is needed, the object can call out to a factory or
* service locator:
*
*
class Stopwatch {
* final TimeSource timeSource;
* Stopwatch () {
* timeSource = DefaultTimeSource.getInstance();
* }
* void start() { ... }
* long stop() { ... }
* }
*
* In org.testifyproject.testifyprojectciding between these traditional approaches to org.testifyproject.testifyprojectpendency
* resolution, a programmer must make trade-offs. Constructors are more
* concise but restrictive. Factories org.testifyproject.testifyprojectcouple the client and implementation
* to some extent but require boilerplate code. Service locators org.testifyproject.testifyprojectcouple even
* further but reduce org.testifyproject.testifyprojectpile time type safety. All three approaches inhibit
* unit testing. For example, if the programmer uses a factory, each test
* against code that org.testifyproject.testifyprojectpends on the factory will have to mock out the factory
* and remember to clean up after itself or else risk side effects:
*
*
void testStopwatch() {
* TimeSource original = DefaultTimeSource.getInstance();
* DefaultTimeSource.setInstance(new MockTimeSource());
* try {
* // Now, we can actually test Stopwatch.
* Stopwatch sw = new Stopwatch();
* ...
* } finally {
* DefaultTimeSource.setInstance(original);
* }
* }
*
* 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
* org.testifyproject.testifyprojectpendencies 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 org.testifyproject.testifyprojectcides 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, org.testifyproject.testifyprojectplexity, and
* error-proneness.
*
*
Dependency injection addresses all of these issues. Instead of
* the programmer calling a constructor or factory, a tool called a
* org.testifyproject.testifyprojectpendency injector passes org.testifyproject.testifyprojectpendencies to objects:
*
*
class Stopwatch {
* final TimeSource timeSource;
* @Inject Stopwatch(TimeSource TimeSource) {
* this.TimeSource = TimeSource;
* }
* void start() { ... }
* long stop() { ... }
* }
*
* The injector further passes org.testifyproject.testifyprojectpendencies to other org.testifyproject.testifyprojectpendencies until it
* constructs the entire object graph. For example, suppose the programmer
* asked an injector to create a StopwatchWidget instance:
*
*
/** GUI for a Stopwatch */
* class StopwatchWidget {
* @Inject StopwatchWidget(Stopwatch sw) { ... }
* ...
* }
*
* The injector might:
*
* - Find a TimeSource
*
- Construct a Stopwatch with the TimeSource
*
- Construct a StopwatchWidget with the Stopwatch
*
*
* This leaves the programmer's code clean, flexible, and relatively free
* of org.testifyproject.testifyprojectpendency-related infrastructure.
*
*
In unit tests, the programmer can now construct objects directly
* (without an injector) and pass in mock org.testifyproject.testifyprojectpendencies. The programmer no
* longer needs to set up and tear down factories or service locators in each
* test. This greatly simplifies our unit test:
*
*
void testStopwatch() {
* Stopwatch sw = new Stopwatch(new MockTimeSource());
* ...
* }
*
* The total org.testifyproject.testifyprojectcrease in unit-test org.testifyproject.testifyprojectplexity is proportional to the
* product of the number of unit tests and the number of org.testifyproject.testifyprojectpendencies.
*
*
This package provides org.testifyproject.testifyprojectpendency injection annotations that enable
* portable classes, but it leaves external org.testifyproject.testifyprojectpendency configuration up to
* the injector implementation. Programmers annotate constructors, methods,
* and fields to advertise their injectability (constructor injection is
* org.testifyproject.testifyprojectmonstrated in the examples above). A org.testifyproject.testifyprojectpendency injector identifies a
* class's org.testifyproject.testifyprojectpendencies by inspecting these annotations, and injects the
* org.testifyproject.testifyprojectpendencies at run time. Moreover, the injector can verify that all
* org.testifyproject.testifyprojectpendencies have been satisfied at build time. A service locator,
* by contrast, cannot org.testifyproject.testifyprojecttect unsatisfied org.testifyproject.testifyprojectpendencies until run time.
*
*
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 org.testifyproject.testifyprojectpile-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 org.testifyproject.testifyprojectpile nor run time. A "container", for
* some org.testifyproject.testifyprojectfinition, can be an injector, but this package specification aims to
* minimize restrictions on injector implementations.
*
* @see javax.inject.Inject @Inject
*/
package javax.inject;