Skip to content

Commit 5025c61

Browse files
committed
Consistent use of AnnotatedElementUtils.findMergedAnnotation/hasAnnotation
Issue: SPR-13440
1 parent 311d4c9 commit 5025c61

File tree

33 files changed

+357
-238
lines changed

33 files changed

+357
-238
lines changed

spring-aspects/src/main/java/org/springframework/scheduling/aspectj/AnnotationAsyncExecutionAspect.aj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package org.springframework.scheduling.aspectj;
1919
import java.lang.reflect.Method;
2020
import java.util.concurrent.Future;
2121

22-
import org.springframework.core.annotation.AnnotationUtils;
22+
import org.springframework.core.annotation.AnnotatedElementUtils;
2323
import org.springframework.scheduling.annotation.Async;
2424

2525
/**
@@ -68,9 +68,9 @@ public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspec
6868
protected String getExecutorQualifier(Method method) {
6969
// Maintainer's note: changes made here should also be made in
7070
// AnnotationAsyncExecutionInterceptor#getExecutorQualifier
71-
Async async = AnnotationUtils.findAnnotation(method, Async.class);
71+
Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
7272
if (async == null) {
73-
async = AnnotationUtils.findAnnotation(method.getDeclaringClass(), Async.class);
73+
async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
7474
}
7575
return (async != null ? async.value() : null);
7676
}

spring-context/src/main/java/org/springframework/context/annotation/BeanAnnotationHelper.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,30 +18,27 @@
1818

1919
import java.lang.reflect.Method;
2020

21-
import org.springframework.core.annotation.AnnotationUtils;
21+
import org.springframework.core.annotation.AnnotatedElementUtils;
2222

2323
/**
2424
* Utilities for processing {@link Bean}-annotated methods.
2525
*
2626
* @author Chris Beams
27+
* @author Juergen Hoeller
2728
* @since 3.1
2829
*/
2930
class BeanAnnotationHelper {
3031

31-
/**
32-
* Return whether the given method is directly or indirectly annotated with
33-
* the {@link Bean} annotation.
34-
*/
3532
public static boolean isBeanAnnotated(Method method) {
36-
return (AnnotationUtils.findAnnotation(method, Bean.class) != null);
33+
return AnnotatedElementUtils.hasAnnotation(method, Bean.class);
3734
}
3835

3936
public static String determineBeanNameFor(Method beanMethod) {
4037
// By default, the bean name is the name of the @Bean-annotated method
4138
String beanName = beanMethod.getName();
4239

4340
// Check to see if the user has explicitly set a custom bean name...
44-
Bean bean = AnnotationUtils.findAnnotation(beanMethod, Bean.class);
41+
Bean bean = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Bean.class);
4542
if (bean != null && bean.name().length > 0) {
4643
beanName = bean.name()[0];
4744
}

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import org.springframework.cglib.proxy.NoOp;
4646
import org.springframework.cglib.transform.ClassEmitterTransformer;
4747
import org.springframework.cglib.transform.TransformingClassGenerator;
48-
import org.springframework.core.annotation.AnnotationUtils;
48+
import org.springframework.core.annotation.AnnotatedElementUtils;
4949
import org.springframework.objenesis.ObjenesisException;
5050
import org.springframework.objenesis.SpringObjenesis;
5151
import org.springframework.util.Assert;
@@ -311,7 +311,7 @@ public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object
311311
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
312312

313313
// Determine whether this bean is a scoped-proxy
314-
Scope scope = AnnotationUtils.findAnnotation(beanMethod, Scope.class);
314+
Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
315315
if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
316316
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
317317
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {

spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,7 +35,6 @@
3535
import org.springframework.core.BridgeMethodResolver;
3636
import org.springframework.core.ResolvableType;
3737
import org.springframework.core.annotation.AnnotatedElementUtils;
38-
import org.springframework.core.annotation.AnnotationUtils;
3938
import org.springframework.core.annotation.Order;
4039
import org.springframework.expression.EvaluationContext;
4140
import org.springframework.util.Assert;
@@ -214,7 +213,7 @@ private boolean shouldHandle(ApplicationEvent event, Object[] args) {
214213
}
215214

216215
protected <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
217-
return AnnotationUtils.findAnnotation(this.method, annotationType);
216+
return AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType);
218217
}
219218

220219
/**

spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,8 +39,8 @@
3939
import org.springframework.context.ApplicationListener;
4040
import org.springframework.context.ConfigurableApplicationContext;
4141
import org.springframework.core.MethodIntrospector;
42+
import org.springframework.core.annotation.AnnotatedElementUtils;
4243
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
43-
import org.springframework.core.annotation.AnnotationUtils;
4444
import org.springframework.util.Assert;
4545

4646
/**
@@ -129,7 +129,7 @@ protected void processBean(final List<EventListenerFactory> factories, final Str
129129
new MethodIntrospector.MetadataLookup<EventListener>() {
130130
@Override
131131
public EventListener inspect(Method method) {
132-
return AnnotationUtils.findAnnotation(method, EventListener.class);
132+
return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
133133
}
134134
});
135135
if (annotatedMethods.isEmpty()) {

spring-context/src/main/java/org/springframework/scheduling/annotation/AnnotationAsyncExecutionInterceptor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import org.springframework.aop.interceptor.AsyncExecutionInterceptor;
2323
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
24-
import org.springframework.core.annotation.AnnotationUtils;
24+
import org.springframework.core.annotation.AnnotatedElementUtils;
2525

2626
/**
2727
* Specialization of {@link AsyncExecutionInterceptor} that delegates method execution to
@@ -78,9 +78,9 @@ public AnnotationAsyncExecutionInterceptor(Executor defaultExecutor, AsyncUncaug
7878
protected String getExecutorQualifier(Method method) {
7979
// Maintainer's note: changes made here should also be made in
8080
// AnnotationAsyncExecutionAspect#getExecutorQualifier
81-
Async async = AnnotationUtils.findAnnotation(method, Async.class);
81+
Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
8282
if (async == null) {
83-
async = AnnotationUtils.findAnnotation(method.getDeclaringClass(), Async.class);
83+
async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
8484
}
8585
return (async != null ? async.value() : null);
8686
}

spring-context/src/test/java/org/springframework/context/event/AnnotationDrivenEventListenerTests.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.springframework.context.event.test.Identifiable;
5555
import org.springframework.context.event.test.TestEvent;
5656
import org.springframework.context.support.ClassPathXmlApplicationContext;
57+
import org.springframework.core.annotation.AliasFor;
5758
import org.springframework.core.annotation.Order;
5859
import org.springframework.scheduling.annotation.Async;
5960
import org.springframework.scheduling.annotation.EnableAsync;
@@ -868,6 +869,16 @@ public void handleString(GenericEventPojo<String> value) {
868869
}
869870

870871

872+
873+
@EventListener
874+
@Retention(RetentionPolicy.RUNTIME)
875+
public @interface ConditionalEvent {
876+
877+
@AliasFor(annotation = EventListener.class, attribute = "condition")
878+
String value();
879+
}
880+
881+
871882
@Component
872883
static class ConditionalEventListener extends TestEventListener {
873884

@@ -883,12 +894,12 @@ public void handleString(String payload) {
883894
super.handleString(payload);
884895
}
885896

886-
@EventListener(condition = "#root.event.timestamp > #p0")
897+
@ConditionalEvent("#root.event.timestamp > #p0")
887898
public void handleTimestamp(Long timestamp) {
888899
collectEvent(timestamp);
889900
}
890901

891-
@EventListener(condition = "@conditionEvaluator.valid(#p0)")
902+
@ConditionalEvent("@conditionEvaluator.valid(#p0)")
892903
public void handleRatio(Double ratio) {
893904
collectEvent(ratio);
894905
}

spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,15 @@ public static boolean isAnnotated(AnnotatedElement element, final Class<? extend
271271
Assert.notNull(element, "AnnotatedElement must not be null");
272272
Assert.notNull(annotationType, "annotationType must not be null");
273273

274+
// Shortcut: directly present on the element, with no processing needed?
275+
if (element.isAnnotationPresent(annotationType)) {
276+
return true;
277+
}
278+
274279
return Boolean.TRUE.equals(searchWithGetSemantics(element, annotationType, null, new SimpleAnnotationProcessor<Boolean>() {
275280
@Override
276281
public Boolean process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) {
277-
boolean found = annotation.annotationType() == annotationType;
282+
boolean found = (annotation.annotationType() == annotationType);
278283
return (found ? Boolean.TRUE : CONTINUE);
279284
}
280285
}));
@@ -324,6 +329,15 @@ public Boolean process(AnnotatedElement annotatedElement, Annotation annotation,
324329
* @see AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement)
325330
*/
326331
public static <A extends Annotation> A getMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
332+
Assert.notNull(annotationType, "annotationType must not be null");
333+
334+
// Shortcut: directly present on the element, with no merging needed?
335+
A annotation = element.getAnnotation(annotationType);
336+
if (annotation != null) {
337+
return AnnotationUtils.synthesizeAnnotation(annotation, element);
338+
}
339+
340+
// Exhaustive retrieval of merged annotation attributes...
327341
AnnotationAttributes attributes = getMergedAnnotationAttributes(element, annotationType);
328342
return AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element);
329343
}
@@ -412,6 +426,38 @@ public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElemen
412426
return attributes;
413427
}
414428

429+
/**
430+
* Determine if an annotation of the specified {@code annotationType}
431+
* is <em>available</em> on the supplied {@link AnnotatedElement} or
432+
* within the annotation hierarchy <em>above</em> the specified element.
433+
* <p>If this method returns {@code true}, then {@link #findMergedAnnotationAttributes}
434+
* will return a non-null value.
435+
* <p>This method follows <em>find semantics</em> as described in the
436+
* {@linkplain AnnotatedElementUtils class-level javadoc}.
437+
* @param element the annotated element
438+
* @param annotationType the annotation type to find
439+
* @return {@code true} if a matching annotation is present
440+
* @since 4.3
441+
*/
442+
public static boolean hasAnnotation(AnnotatedElement element, final Class<? extends Annotation> annotationType) {
443+
Assert.notNull(element, "AnnotatedElement must not be null");
444+
Assert.notNull(annotationType, "annotationType must not be null");
445+
446+
// Shortcut: directly present on the element, with no processing needed?
447+
if (element.isAnnotationPresent(annotationType)) {
448+
return true;
449+
}
450+
451+
return Boolean.TRUE.equals(searchWithFindSemantics(element, annotationType, annotationType.getName(),
452+
new SimpleAnnotationProcessor<Boolean>() {
453+
@Override
454+
public Boolean process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) {
455+
boolean found = (annotation.annotationType() == annotationType);
456+
return (found ? Boolean.TRUE : CONTINUE);
457+
}
458+
}));
459+
}
460+
415461
/**
416462
* Find the first annotation of the specified {@code annotationType} within
417463
* the annotation hierarchy <em>above</em> the supplied {@code element},
@@ -430,6 +476,14 @@ public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElemen
430476
*/
431477
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
432478
Assert.notNull(annotationType, "annotationType must not be null");
479+
480+
// Shortcut: directly present on the element, with no merging needed?
481+
A annotation = element.getDeclaredAnnotation(annotationType);
482+
if (annotation != null) {
483+
return AnnotationUtils.synthesizeAnnotation(annotation, element);
484+
}
485+
486+
// Exhaustive retrieval of merged annotation attributes...
433487
AnnotationAttributes attributes = findMergedAnnotationAttributes(element, annotationType, false, false);
434488
return AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element);
435489
}
@@ -483,9 +537,8 @@ public static <A extends Annotation> Set<A> findAllMergedAnnotations(AnnotatedEl
483537
Assert.notNull(element, "AnnotatedElement must not be null");
484538
Assert.notNull(annotationType, "annotationType must not be null");
485539

486-
MergedAnnotationAttributesProcessor processor = new MergedAnnotationAttributesProcessor(annotationType, null,
487-
false, false, true);
488-
540+
MergedAnnotationAttributesProcessor processor =
541+
new MergedAnnotationAttributesProcessor(annotationType, null, false, false, true);
489542
searchWithFindSemantics(element, annotationType, annotationType.getName(), processor);
490543

491544
Set<A> annotations = new LinkedHashSet<A>();
@@ -831,8 +884,7 @@ private static <T> T searchWithFindSemantics(AnnotatedElement element, Class<? e
831884
try {
832885
// Locally declared annotations (ignoring @Inherited)
833886
Annotation[] annotations = element.getDeclaredAnnotations();
834-
835-
List<T> aggregatedResults = processor.aggregates() ? new ArrayList<T>() : null;
887+
List<T> aggregatedResults = (processor.aggregates() ? new ArrayList<T>() : null);
836888

837889
// Search in local annotations
838890
for (Annotation annotation : annotations) {

spring-jms/src/main/java/org/springframework/jms/config/MethodJmsListenerEndpoint.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import org.springframework.beans.factory.BeanFactoryAware;
2626
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
2727
import org.springframework.beans.factory.config.EmbeddedValueResolver;
28-
import org.springframework.core.annotation.AnnotationUtils;
28+
import org.springframework.core.annotation.AnnotatedElementUtils;
2929
import org.springframework.jms.listener.MessageListenerContainer;
3030
import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter;
3131
import org.springframework.jms.support.converter.MessageConverter;
@@ -187,13 +187,11 @@ protected String getDefaultResponseDestination() {
187187
}
188188

189189
private SendTo getSendTo(Method specificMethod) {
190-
SendTo ann = AnnotationUtils.getAnnotation(specificMethod, SendTo.class);
191-
if (ann != null) {
192-
return ann;
193-
}
194-
else {
195-
return AnnotationUtils.getAnnotation(specificMethod.getDeclaringClass(), SendTo.class);
190+
SendTo ann = AnnotatedElementUtils.findMergedAnnotation(specificMethod, SendTo.class);
191+
if (ann == null) {
192+
ann = AnnotatedElementUtils.findMergedAnnotation(specificMethod.getDeclaringClass(), SendTo.class);
196193
}
194+
return ann;
197195
}
198196

199197
private String resolve(String value) {

0 commit comments

Comments
 (0)