-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathScopes.java
133 lines (115 loc) · 4.14 KB
/
Scopes.java
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
/**
* Copyright (C) 2006 Google 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.
*/
package com.google.inject;
import com.google.inject.internal.Errors;
import com.google.inject.internal.InternalFactory;
import com.google.inject.internal.Scoping;
import com.google.inject.spi.CachingProvider;
import java.lang.annotation.Annotation;
/**
* Built-in scope implementations.
*
* @author [email protected] (Bob Lee)
*/
public class Scopes {
private Scopes() {}
/**
* One instance per {@link Injector}. Also see {@code @}{@link Singleton}.
*/
public static final Scope SINGLETON = new Scope() {
public <T> Provider<T> scope(Key<T> key, final Provider<T> creator) {
return new CachingProvider<T>() {
private volatile T instance;
// DCL on a volatile is safe as of Java 5, which we obviously require.
@SuppressWarnings("DoubleCheckedLocking")
public T get() {
if (instance == null) {
/*
* Use a pretty coarse lock. We don't want to run into deadlocks
* when two threads try to load circularly-dependent objects.
* Maybe one of these days we will identify independent graphs of
* objects and offer to load them in parallel.
*/
synchronized (InjectorImpl.class) {
if (instance == null) {
instance = creator.get();
}
}
}
return instance;
}
public T getCachedValue() {
return instance;
}
public String toString() {
return String.format("%s[%s]", creator, SINGLETON);
}
};
}
@Override public String toString() {
return "Scopes.SINGLETON";
}
};
/**
* No scope; the same as not applying any scope at all. Each time the
* Injector obtains an instance of an object with "no scope", it injects this
* instance then immediately forgets it. When the next request for the same
* binding arrives it will need to obtain the instance over again.
*
* <p>This exists only in case a class has been annotated with a scope
* annotation such as {@link Singleton @Singleton}, and you need to override
* this to "no scope" in your binding.
*
* @since 2.0
*/
public static final Scope NO_SCOPE = new Scope() {
public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
return unscoped;
}
@Override public String toString() {
return "Scopes.NO_SCOPE";
}
};
/** Scopes an internal factory. */
static <T> InternalFactory<? extends T> scope(Key<T> key, InjectorImpl injector,
InternalFactory<? extends T> creator, Scoping scoping) {
if (scoping.isNoScope()) {
return creator;
}
Scope scope = scoping.getScopeInstance();
Provider<T> scoped
= scope.scope(key, new ProviderToInternalFactoryAdapter<T>(injector, creator));
return new InternalFactoryToProviderAdapter<T>(
Initializables.<Provider<? extends T>>of(scoped));
}
/**
* Replaces annotation scopes with instance scopes using the Injector's annotation-to-instance
* map. If the scope annotation has no corresponding instance, an error will be added and unscoped
* will be retuned.
*/
static Scoping makeInjectable(Scoping scoping, InjectorImpl injector, Errors errors) {
Class<? extends Annotation> scopeAnnotation = scoping.getScopeAnnotation();
if (scopeAnnotation == null) {
return scoping;
}
Scope scope = injector.state.getScope(scopeAnnotation);
if (scope != null) {
return Scoping.forInstance(scope);
}
errors.scopeNotFound(scopeAnnotation);
return Scoping.UNSCOPED;
}
}