-
Notifications
You must be signed in to change notification settings - Fork 0
/
Injection.java
196 lines (181 loc) · 5.36 KB
/
Injection.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
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
package ml.alternet.discover;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.PACKAGE;
import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This interface contains qualifiers used in conjunction with a CDI container
* (JSR 330).
*
* You are not compelled to use the discovery service with a CDI container, but
* if you want to inject classes to lookup (specifically with a variant), the
* annotations defined here may help.
*
* Even if you used a CDI container, you are not compelled to inject every
* classes to lookup, just the ones you want to or have to inject.
*
* <ul>
* <li>{@link LookupKey} generates an entry in <tt>META-INF/xservices/</tt></li>
* <li>{@link Injection.LookupKey} qualifies an instance to inject</li>
* <li>{@link Injection.Producer} generates a class producer for injections</li>
* </ul>
*
* <h3>Usage</h3>
*
* <h4>Start situation (without injection)</h4>
*
* For example, consider a constructor :
*
* <pre>
* public A(B b) {
* //
* }
* </pre>
*
* where B is an interface :
*
* <pre>
* public interface B {
* //
* }
* </pre>
*
* which has several implementations :
*
* <pre>
* @LookupKey(forClass = B.class, variant = "variant1")
* public class B1 implements B {
* //
* }
* </pre>
*
* and :
*
* <pre>
* @LookupKey(forClass = B.class, variant = "variant2")
* public class B2 implements B {
* //
* }
* </pre>
*
* You want to inject the right class ? See below...
*
* <h4>Target situation (with injection)</h4>
*
* First, in the constructor (or directly in the field, up to you) one have to
* indicates that an instance have to be injected :
*
* <pre>
* @javax.inject.Inject
* public A(@Injection.LookupKey("variant1") B b) {
* //
* }
* </pre>
*
* Then you have to set on the interface which variant you want to produce :
*
* <pre>
* @Injection.Producer(variant = "variant1")
* public interface B {
* //
* }
* </pre>
*
* A producer class will be generated at compile time, that will perform the
* lookup with the specified variant. At runtime, the container will inject the
* instance supplied by the producer that matches both the expected target class
* and the variant, if any.
*
* <h3>Other usage</h3>
*
* Sometimes, the developer doesn't own the type to inject neither their
* implementations ; it is still possible to set the annotations on some code
* owned by the developer, for example one of its package and specify both the
* implementation and the target class.
*
* If a specific producer have to match a general-purpose variant, and have to
* lookup for a different variant, it is also possible to specify a different
* variant target.
*
* @author Philippe Poulard
*/
public interface Injection {
/**
* Use this qualifier to inject an instance to lookup with the discovery
* service.
*/
@javax.inject.Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ METHOD, FIELD, PARAMETER /* , TYPE, CONSTRUCTOR */})
@interface LookupKey {
/**
* The variant to inject, may match a producer.
*
* @return The variant to inject.
*
* @see Producer
*/
String variant() default "";
}
/**
* Generates a producer for the class or interface that will be used with
* the lookup key qualifier. The producer will supply an instance found by
* the discovery service.
*
* @see LookupKey
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ TYPE, PACKAGE })
@Repeatable(Producers.class)
@interface Producer {
/**
* The class to produce ; by default it is the class on which this
* annotation is set ; if this annotation is set on a package, the value
* MUST be supplied. The discovery service will perform a lookup for
* that class.
*
* @return The class to produce
*/
Class<?> forClass() default Void.class;
/**
* The variant to inject by this producer, that a lookup key may match.
*
* @return The variant to inject
*/
String variant() default "";
/**
* The variant to lookup ; if not specified, the lookup variant will be
* the same as the variant of the qualifier lookup key. For the unlikely
* case where the inject lookup key would have a variant, but for which
* the producer have to lookup for an implementation without a variant,
* fill this value with only whitespace.
*
* @return The variant to lookup.
*/
String lookupVariant() default "";
}
/**
* Allow to repeat a producer annotation.
*
* @see Producer
*
* @author Philippe Poulard
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ TYPE })
@interface Producers {
/**
* Return the producers.
*
* @return The producers.
*/
Producer[] value();
}
}