|
21 | 21 |
|
22 | 22 | import javax.annotation.PostConstruct;
|
23 | 23 | import javax.annotation.PreDestroy;
|
| 24 | +import javax.interceptor.ExcludeClassInterceptors; |
| 25 | +import javax.interceptor.ExcludeDefaultInterceptors; |
24 | 26 | import javax.interceptor.Interceptor;
|
25 |
| -import javax.interceptor.*; |
| 27 | +import javax.interceptor.Interceptors; |
26 | 28 | import java.lang.annotation.Annotation;
|
27 |
| -import java.lang.reflect.AnnotatedElement; |
28 | 29 | import java.lang.reflect.Constructor;
|
29 | 30 | import java.lang.reflect.Executable;
|
30 | 31 | import java.lang.reflect.Method;
|
31 | 32 | import java.util.*;
|
32 | 33 |
|
33 | 34 | import static java.util.Arrays.asList;
|
34 | 35 | import static java.util.Collections.*;
|
35 |
| -import static java.util.stream.Collectors.toList; |
36 | 36 | import static org.geektimes.commons.lang.util.AnnotationUtils.findAnnotation;
|
37 | 37 | import static org.geektimes.commons.lang.util.AnnotationUtils.isMetaAnnotation;
|
38 | 38 | import static org.geektimes.interceptor.util.InterceptorUtils.*;
|
@@ -60,30 +60,23 @@ public class DefaultInterceptorManager implements InterceptorManager {
|
60 | 60 | */
|
61 | 61 | private final Map<InterceptorBindings, SortedSet<Object>> bindingInterceptors;
|
62 | 62 |
|
63 |
| - /** |
64 |
| - * The map the {@link InterceptorBinding interceptorBindings} or synthetic annotations to annotation types |
65 |
| - */ |
66 |
| - private final Map<Annotation, Class<? extends Annotation>> interceptorBindings; |
67 |
| - |
68 | 63 | /**
|
69 | 64 | * The cache for {@link Method} or {@link Constructor} mapping the prioritized {@link Interceptor @Interceptor}
|
70 |
| - * instances |
| 65 | + * {@link Class classes} |
71 | 66 | */
|
72 |
| - private final Map<Executable, List<Object>> executableInterceptors; |
| 67 | + private final Map<Executable, List<Class<?>>> executableInterceptorClasses; |
73 | 68 |
|
74 | 69 | /**
|
75 |
| - * The cache for {@link Method} or {@link Constructor} mapping the prioritized {@link Interceptor @Interceptor} |
76 |
| - * {@link Class classes} |
| 70 | + * The repository for {@link Interceptor @Interceptor} classes and instances |
77 | 71 | */
|
78 |
| - private final Map<Executable, List<Class<?>>> executableInterceptorClasses; |
| 72 | + private final Map<Class<?>, Object> interceptorRepository; |
79 | 73 |
|
80 | 74 | public DefaultInterceptorManager() {
|
81 |
| - this.interceptorBindings = new HashMap<>(); |
82 | 75 | this.interceptorBindingTypes = new HashSet<>();
|
83 | 76 | this.interceptorInfoRepository = new TreeMap<>(PriorityComparator.INSTANCE);
|
84 | 77 | this.bindingInterceptors = new HashMap<>();
|
85 |
| - this.executableInterceptors = new HashMap<>(); |
86 | 78 | this.executableInterceptorClasses = new HashMap<>();
|
| 79 | + this.interceptorRepository = new HashMap<>(); |
87 | 80 | registerDefaultInterceptorBindingType();
|
88 | 81 | }
|
89 | 82 |
|
@@ -137,38 +130,78 @@ public InterceptorInfo getInterceptorInfo(Class<?> interceptorClass) throws Ille
|
137 | 130 |
|
138 | 131 | @Override
|
139 | 132 | public List<Object> resolveInterceptors(Executable executable, Object... defaultInterceptors) {
|
140 |
| - return executableInterceptors.computeIfAbsent(executable, e -> { |
| 133 | + List<Object> interceptors = new LinkedList<>(); |
| 134 | + |
| 135 | + if (!isExcludedDefaultInterceptors(executable)) { |
| 136 | + // 1. Default interceptors are invoked first |
| 137 | + interceptors.addAll(asList(defaultInterceptors)); |
| 138 | + } |
| 139 | + |
| 140 | + for (Class<?> interceptorClass : resolveInterceptorClasses(executable)) { |
| 141 | + Object interceptor = interceptorRepository.computeIfAbsent(interceptorClass, this::unwrap); |
| 142 | + interceptors.add(interceptor); |
| 143 | + } |
| 144 | + |
| 145 | + return interceptors; |
| 146 | + } |
| 147 | + |
| 148 | + @Override |
| 149 | + public List<Class<?>> resolveInterceptorClasses(Executable executable, Class<?>... defaultInterceptorClasses) { |
| 150 | + return executableInterceptorClasses.computeIfAbsent(executable, e -> { |
141 | 151 |
|
142 |
| - List<Object> interceptors = new LinkedList<>(); |
| 152 | + List<Class<?>> interceptorClasses = new LinkedList<>(); |
143 | 153 |
|
144 | 154 | if (!isExcludedDefaultInterceptors(executable)) {
|
145 | 155 | // 1. Default interceptors are invoked first
|
146 |
| - interceptors.addAll(asList(defaultInterceptors)); |
| 156 | + interceptorClasses.addAll(asList(defaultInterceptorClasses)); |
147 | 157 | }
|
148 | 158 |
|
149 | 159 | // Resolve interceptors using @Interceptors
|
150 | 160 | // 2. Interceptors declared by applying the Interceptors annotation at class-level to the target
|
151 | 161 | // class are invoked next.
|
152 | 162 | // 3. Interceptors declared by applying the Interceptors annotation at method- or constructor-level
|
153 | 163 | // are invoked next.
|
154 |
| - List<Object> annotatedInterceptors = resolveAnnotatedInterceptors(executable); |
155 |
| - interceptors.addAll(annotatedInterceptors); |
| 164 | + interceptorClasses.addAll(resolveAnnotatedInterceptorClasses(executable)); |
156 | 165 |
|
157 | 166 | // Resolve interceptors using Interceptor Bindings
|
158 | 167 | // 4. Interceptors declared using interceptor bindings are invoked next.
|
159 |
| - SortedSet<Object> bindingInterceptors = resolveBindingInterceptors(executable); |
160 |
| - interceptors.addAll(bindingInterceptors); |
| 168 | + interceptorClasses.addAll(resolveBindingInterceptorClasses(executable)); |
161 | 169 |
|
162 |
| - // 5.2.1 Use of the Priority Annotation in Ordering Interceptors |
163 |
| - sortInterceptors(interceptors); |
164 |
| - |
165 |
| - return unmodifiableList(interceptors); |
| 170 | + return unmodifiableList(interceptorClasses); |
166 | 171 | });
|
167 | 172 | }
|
168 | 173 |
|
169 |
| - @Override |
170 |
| - public List<Class<?>> resolveInterceptorClasses(Executable executable, Class<?>... defaultInterceptorClasses) { |
171 |
| - return null; |
| 174 | + /** |
| 175 | + * The set of interceptor bindings for a method or constructor are those applied to the target class |
| 176 | + * combined with those applied at method level or constructor level. |
| 177 | + * Note that the interceptor bindings applied to the target class may include those inherited from |
| 178 | + * its superclasses. |
| 179 | + * |
| 180 | + * @param executable {@link Executable} |
| 181 | + * @return |
| 182 | + */ |
| 183 | + private List<Class<?>> resolveBindingInterceptorClasses(Executable executable) { |
| 184 | + List<Class<?>> bindingInterceptorClasses = new LinkedList<>(); |
| 185 | + |
| 186 | + for (InterceptorInfo interceptorInfo : interceptorInfoRepository.values()) { |
| 187 | + InterceptorBindings interceptorBindings = interceptorInfo.getInterceptorBindings(); |
| 188 | + |
| 189 | + boolean matched = !interceptorBindings.getInterceptorBindingTypes().isEmpty(); |
| 190 | + for (InterceptorBindingInfo interceptorBindingInfo : interceptorBindings) { |
| 191 | + Class<? extends Annotation> interceptorBindingType = interceptorBindingInfo.getDeclaredAnnotationType(); |
| 192 | + Annotation annotation = searchAnnotation(executable, interceptorBindingType); |
| 193 | + matched &= interceptorBindingInfo.equals(annotation); |
| 194 | + } |
| 195 | + |
| 196 | + if (matched) { |
| 197 | + bindingInterceptorClasses.add(interceptorInfo.getInterceptorClass()); |
| 198 | + } |
| 199 | + } |
| 200 | + |
| 201 | + // 5.2.1 Use of the Priority Annotation in Ordering Interceptors |
| 202 | + sortInterceptors(bindingInterceptorClasses); |
| 203 | + |
| 204 | + return bindingInterceptorClasses; |
172 | 205 | }
|
173 | 206 |
|
174 | 207 |
|
@@ -238,11 +271,6 @@ private boolean isExcludedDefaultInterceptors(Executable executable) {
|
238 | 271 | return false;
|
239 | 272 | }
|
240 | 273 |
|
241 |
| - private SortedSet<Object> resolveBindingInterceptors(Executable executable) { |
242 |
| - InterceptorBindings interceptorBindings = resolveInterceptorBindings(executable); |
243 |
| - return unmodifiableSortedSet(bindingInterceptors.getOrDefault(interceptorBindings, emptySortedSet())); |
244 |
| - } |
245 |
| - |
246 | 274 | /**
|
247 | 275 | * Interceptors declared by applying the Interceptors annotation at class-level to the target
|
248 | 276 | * class are invoked next.
|
@@ -278,79 +306,4 @@ private List<Class<?>> resolveAnnotatedInterceptorClasses(Executable executable)
|
278 | 306 | return interceptorClasses;
|
279 | 307 | }
|
280 | 308 |
|
281 |
| - /** |
282 |
| - * Interceptors declared by applying the Interceptors annotation at class-level to the target |
283 |
| - * class are invoked next. |
284 |
| - * <p> |
285 |
| - * Interceptors declared by applying the Interceptors annotation at method- or constructor-level are invoked next. |
286 |
| - * |
287 |
| - * @param executable the intercepted of {@linkplain Method method} or {@linkplain Constructor constructor} |
288 |
| - * @return non-null |
289 |
| - * @see Interceptors |
290 |
| - * @see ExcludeClassInterceptors |
291 |
| - */ |
292 |
| - private List<Object> resolveAnnotatedInterceptors(Executable executable) { |
293 |
| - Class<?> componentClass = executable.getDeclaringClass(); |
294 |
| - |
295 |
| - List<Class<?>> interceptorClasses = new LinkedList<>(); |
296 |
| - |
297 |
| - if (!executable.isAnnotationPresent(ExcludeClassInterceptors.class)) { |
298 |
| - Interceptors classInterceptors = searchAnnotation(componentClass, Interceptors.class); |
299 |
| - if (classInterceptors != null) { |
300 |
| - for (Class interceptorClass : classInterceptors.value()) { |
301 |
| - interceptorClasses.add(interceptorClass); |
302 |
| - } |
303 |
| - } |
304 |
| - } |
305 |
| - |
306 |
| - Interceptors executableInterceptors = searchAnnotation(executable, Interceptors.class); |
307 |
| - if (executableInterceptors != null) { |
308 |
| - for (Class interceptorClass : executableInterceptors.value()) { |
309 |
| - interceptorClasses.add(interceptorClass); |
310 |
| - } |
311 |
| - } |
312 |
| - |
313 |
| - return interceptorClasses.stream() |
314 |
| - .map(InterceptorUtils::unwrap) |
315 |
| - .collect(toList()); |
316 |
| - } |
317 |
| - |
318 |
| - |
319 |
| - /** |
320 |
| - * The set of interceptor bindings for a method or constructor are those applied to the target class |
321 |
| - * combined with those applied at method level or constructor level. |
322 |
| - * Note that the interceptor bindings applied to the target class may include those inherited from |
323 |
| - * its superclasses. |
324 |
| - * |
325 |
| - * @param executable {@link Method} or {@link Constructor} |
326 |
| - * @return non-null |
327 |
| - */ |
328 |
| - private InterceptorBindings resolveInterceptorBindings(Executable executable) { |
329 |
| - Set<Annotation> interceptorBindings = doGetInterceptorBindings(executable); |
330 |
| - if (interceptorBindings.isEmpty()) { |
331 |
| - return resolveInterceptorBindings(executable.getDeclaringClass()); |
332 |
| - } |
333 |
| - return new InterceptorBindings(interceptorBindings); |
334 |
| - } |
335 |
| - |
336 |
| - private InterceptorBindings resolveInterceptorBindings(Class<?> componentClass) { |
337 |
| - Set<Annotation> interceptorBindings; |
338 |
| - Class<?> type = componentClass; |
339 |
| - do { |
340 |
| - interceptorBindings = doGetInterceptorBindings(type); |
341 |
| - type = componentClass.getSuperclass(); |
342 |
| - } while (type != Object.class && interceptorBindings.isEmpty()); |
343 |
| - |
344 |
| - return new InterceptorBindings(interceptorBindings); |
345 |
| - } |
346 |
| - |
347 |
| - private Set<Annotation> doGetInterceptorBindings(AnnotatedElement annotatedElement) { |
348 |
| - Set<Annotation> interceptorBindings = new LinkedHashSet<>(); |
349 |
| - for (Annotation annotation : annotatedElement.getAnnotations()) { |
350 |
| - if (isInterceptorBinding(annotation)) { |
351 |
| - interceptorBindings.add(annotation); |
352 |
| - } |
353 |
| - } |
354 |
| - return interceptorBindings; |
355 |
| - } |
356 | 309 | }
|
0 commit comments