Skip to content

Commit b869e81

Browse files
committed
Polish code
1 parent 934e011 commit b869e81

File tree

7 files changed

+86
-118
lines changed

7 files changed

+86
-118
lines changed

projects/stage-1/middleware-frameworks/my-interceptor/src/main/java/org/geektimes/interceptor/DefaultInterceptorManager.java

+62-109
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@
2121

2222
import javax.annotation.PostConstruct;
2323
import javax.annotation.PreDestroy;
24+
import javax.interceptor.ExcludeClassInterceptors;
25+
import javax.interceptor.ExcludeDefaultInterceptors;
2426
import javax.interceptor.Interceptor;
25-
import javax.interceptor.*;
27+
import javax.interceptor.Interceptors;
2628
import java.lang.annotation.Annotation;
27-
import java.lang.reflect.AnnotatedElement;
2829
import java.lang.reflect.Constructor;
2930
import java.lang.reflect.Executable;
3031
import java.lang.reflect.Method;
3132
import java.util.*;
3233

3334
import static java.util.Arrays.asList;
3435
import static java.util.Collections.*;
35-
import static java.util.stream.Collectors.toList;
3636
import static org.geektimes.commons.lang.util.AnnotationUtils.findAnnotation;
3737
import static org.geektimes.commons.lang.util.AnnotationUtils.isMetaAnnotation;
3838
import static org.geektimes.interceptor.util.InterceptorUtils.*;
@@ -60,30 +60,23 @@ public class DefaultInterceptorManager implements InterceptorManager {
6060
*/
6161
private final Map<InterceptorBindings, SortedSet<Object>> bindingInterceptors;
6262

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-
6863
/**
6964
* The cache for {@link Method} or {@link Constructor} mapping the prioritized {@link Interceptor @Interceptor}
70-
* instances
65+
* {@link Class classes}
7166
*/
72-
private final Map<Executable, List<Object>> executableInterceptors;
67+
private final Map<Executable, List<Class<?>>> executableInterceptorClasses;
7368

7469
/**
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
7771
*/
78-
private final Map<Executable, List<Class<?>>> executableInterceptorClasses;
72+
private final Map<Class<?>, Object> interceptorRepository;
7973

8074
public DefaultInterceptorManager() {
81-
this.interceptorBindings = new HashMap<>();
8275
this.interceptorBindingTypes = new HashSet<>();
8376
this.interceptorInfoRepository = new TreeMap<>(PriorityComparator.INSTANCE);
8477
this.bindingInterceptors = new HashMap<>();
85-
this.executableInterceptors = new HashMap<>();
8678
this.executableInterceptorClasses = new HashMap<>();
79+
this.interceptorRepository = new HashMap<>();
8780
registerDefaultInterceptorBindingType();
8881
}
8982

@@ -137,38 +130,78 @@ public InterceptorInfo getInterceptorInfo(Class<?> interceptorClass) throws Ille
137130

138131
@Override
139132
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 -> {
141151

142-
List<Object> interceptors = new LinkedList<>();
152+
List<Class<?>> interceptorClasses = new LinkedList<>();
143153

144154
if (!isExcludedDefaultInterceptors(executable)) {
145155
// 1. Default interceptors are invoked first
146-
interceptors.addAll(asList(defaultInterceptors));
156+
interceptorClasses.addAll(asList(defaultInterceptorClasses));
147157
}
148158

149159
// Resolve interceptors using @Interceptors
150160
// 2. Interceptors declared by applying the Interceptors annotation at class-level to the target
151161
// class are invoked next.
152162
// 3. Interceptors declared by applying the Interceptors annotation at method- or constructor-level
153163
// are invoked next.
154-
List<Object> annotatedInterceptors = resolveAnnotatedInterceptors(executable);
155-
interceptors.addAll(annotatedInterceptors);
164+
interceptorClasses.addAll(resolveAnnotatedInterceptorClasses(executable));
156165

157166
// Resolve interceptors using Interceptor Bindings
158167
// 4. Interceptors declared using interceptor bindings are invoked next.
159-
SortedSet<Object> bindingInterceptors = resolveBindingInterceptors(executable);
160-
interceptors.addAll(bindingInterceptors);
168+
interceptorClasses.addAll(resolveBindingInterceptorClasses(executable));
161169

162-
// 5.2.1 Use of the Priority Annotation in Ordering Interceptors
163-
sortInterceptors(interceptors);
164-
165-
return unmodifiableList(interceptors);
170+
return unmodifiableList(interceptorClasses);
166171
});
167172
}
168173

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;
172205
}
173206

174207

@@ -238,11 +271,6 @@ private boolean isExcludedDefaultInterceptors(Executable executable) {
238271
return false;
239272
}
240273

241-
private SortedSet<Object> resolveBindingInterceptors(Executable executable) {
242-
InterceptorBindings interceptorBindings = resolveInterceptorBindings(executable);
243-
return unmodifiableSortedSet(bindingInterceptors.getOrDefault(interceptorBindings, emptySortedSet()));
244-
}
245-
246274
/**
247275
* Interceptors declared by applying the Interceptors annotation at class-level to the target
248276
* class are invoked next.
@@ -278,79 +306,4 @@ private List<Class<?>> resolveAnnotatedInterceptorClasses(Executable executable)
278306
return interceptorClasses;
279307
}
280308

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-
}
356309
}

projects/stage-1/middleware-frameworks/my-interceptor/src/main/java/org/geektimes/interceptor/InterceptorBindingAttributeFilter.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
*/
3333
public interface InterceptorBindingAttributeFilter extends Predicate<Method> {
3434

35-
Predicate<Method> FILTERS = filters();
36-
3735
default boolean test(Method attributeMethod) {
3836
return accept(attributeMethod);
3937
}
@@ -45,8 +43,8 @@ default boolean test(Method attributeMethod) {
4543
*/
4644
boolean accept(Method attributeMethod);
4745

48-
static Predicate<Method> filters() {
49-
return Predicates.or(loadAsArray(InterceptorBindingAttributeFilter.class));
46+
static Predicate<Method>[] filters() {
47+
return loadAsArray(InterceptorBindingAttributeFilter.class);
5048
}
5149

5250
}

projects/stage-1/middleware-frameworks/my-interceptor/src/main/java/org/geektimes/interceptor/InterceptorBindingInfo.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import java.util.Objects;
2323

2424
import static org.geektimes.commons.lang.util.AnnotationUtils.getAttributesMap;
25-
import static org.geektimes.interceptor.InterceptorBindingAttributeFilter.FILTERS;
25+
import static org.geektimes.interceptor.InterceptorBindingAttributeFilter.filters;
2626
import static org.geektimes.interceptor.util.InterceptorUtils.isAnnotatedInterceptorBinding;
2727

2828
/**
@@ -48,7 +48,7 @@ public InterceptorBindingInfo(Annotation declaredAnnotation) {
4848
this.declaredAnnotation = declaredAnnotation;
4949
this.declaredAnnotationType = declaredAnnotation.annotationType();
5050
this.synthetic = !isAnnotatedInterceptorBinding(declaredAnnotationType);
51-
this.attributes = getAttributesMap(declaredAnnotation, FILTERS);
51+
this.attributes = getAttributesMap(declaredAnnotation, filters());
5252
}
5353

5454
public Class<? extends Annotation> getDeclaredAnnotationType() {
@@ -88,7 +88,14 @@ public Annotation getDeclaredAnnotation() {
8888
* @param interceptorBinding the instance of {@linkplain InterceptorBinding interceptor binding}
8989
* @return non-null
9090
*/
91-
public static InterceptorBindingInfo newInstance(Annotation interceptorBinding) {
91+
public static InterceptorBindingInfo valueOf(Annotation interceptorBinding) {
9292
return new InterceptorBindingInfo(interceptorBinding);
9393
}
94+
95+
public boolean equals(Annotation declaredAnnotation) {
96+
if (declaredAnnotation == null) {
97+
return false;
98+
}
99+
return this.equals(valueOf(declaredAnnotation));
100+
}
94101
}

projects/stage-1/middleware-frameworks/my-interceptor/src/main/java/org/geektimes/interceptor/InterceptorManager.java

+4
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ default boolean isInterceptorBinding(Annotation annotation) {
222222

223223
boolean isInterceptorBindingType(Class<? extends Annotation> annotationType);
224224

225+
default <T> T unwrap(Class<T> type) {
226+
return InterceptorUtils.unwrap(type);
227+
}
228+
225229
static InterceptorManager getInstance(ClassLoader classLoader) {
226230
return loadSpi(InterceptorManager.class, classLoader);
227231
}

projects/stage-1/middleware-frameworks/my-interceptor/src/main/java/org/geektimes/interceptor/util/InterceptorUtils.java

+5
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,11 @@ public static boolean isAnnotatedInterceptorBinding(Class<? extends Annotation>
285285
return isMetaAnnotation(annotationType, InterceptorBinding.class);
286286
}
287287

288+
public static boolean isAnnotatedInterceptorBinding(Executable executable,
289+
Class<? extends Annotation> interceptorBindingType) {
290+
return searchAnnotation(executable, interceptorBindingType) != null;
291+
}
292+
288293
private static IllegalStateException newIllegalStateException(String messagePattern, Object... args) {
289294
return new IllegalStateException(format(messagePattern, args));
290295
}

projects/stage-1/middleware-frameworks/my-interceptor/src/test/java/org/geektimes/interceptor/InterceptorBindingInfoTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.junit.Test;
2020

21+
import static org.geektimes.interceptor.InterceptorBindingInfo.valueOf;
2122
import static org.junit.Assert.*;
2223

2324
/**
@@ -33,7 +34,7 @@ public class InterceptorBindingInfoTest {
3334
@Logging(name = "test")
3435
public void test() throws Throwable {
3536
Logging logging = this.getClass().getAnnotation(Logging.class);
36-
InterceptorBindingInfo info = new InterceptorBindingInfo(logging);
37+
InterceptorBindingInfo info = valueOf(logging);
3738
assertEquals(Logging.class, info.getDeclaredAnnotationType());
3839
assertFalse(info.isSynthetic());
3940
assertTrue(info.getAttributes().isEmpty());
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
org.geektimes.interceptor.AlwaysFalseInterceptorBindingAttributeFilter
1+
# org.geektimes.interceptor.AlwaysFalseInterceptorBindingAttributeFilter

0 commit comments

Comments
 (0)