Skip to content

Commit d72d376

Browse files
committed
Avoid unnecessary annotation introspection on framework methods
Issue: SPR-16933
1 parent f155d21 commit d72d376

File tree

4 files changed

+41
-16
lines changed

4 files changed

+41
-16
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ public ConditionalCallbackFilter(Callback[] callbacks) {
188188
@Override
189189
public int accept(Method method) {
190190
for (int i = 0; i < this.callbacks.length; i++) {
191-
if (!(this.callbacks[i] instanceof ConditionalCallback) ||
192-
((ConditionalCallback) this.callbacks[i]).isMatch(method)) {
191+
Callback callback = this.callbacks[i];
192+
if (!(callback instanceof ConditionalCallback) || ((ConditionalCallback) callback).isMatch(method)) {
193193
return i;
194194
}
195195
}
@@ -285,6 +285,10 @@ public Object intercept(Object obj, Method method, Object[] args, MethodProxy pr
285285

286286
@Override
287287
public boolean isMatch(Method candidateMethod) {
288+
return isSetBeanFactory(candidateMethod);
289+
}
290+
291+
public static boolean isSetBeanFactory(Method candidateMethod) {
288292
return (candidateMethod.getName().equals("setBeanFactory") &&
289293
candidateMethod.getParameterCount() == 1 &&
290294
BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
@@ -430,6 +434,7 @@ private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
430434
@Override
431435
public boolean isMatch(Method candidateMethod) {
432436
return (candidateMethod.getDeclaringClass() != Object.class &&
437+
!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
433438
BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
434439
}
435440

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -41,6 +41,7 @@
4141
import org.springframework.core.annotation.AnnotatedElementUtils;
4242
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
4343
import org.springframework.lang.Nullable;
44+
import org.springframework.stereotype.Component;
4445
import org.springframework.util.Assert;
4546
import org.springframework.util.CollectionUtils;
4647

@@ -137,7 +138,7 @@ protected List<EventListenerFactory> getEventListenerFactories() {
137138
protected void processBean(
138139
final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
139140

140-
if (!this.nonAnnotatedClasses.contains(targetType)) {
141+
if (!this.nonAnnotatedClasses.contains(targetType) && !isSpringContainerClass(targetType)) {
141142
Map<Method, EventListener> annotatedMethods = null;
142143
try {
143144
annotatedMethods = MethodIntrospector.selectMethods(targetType,
@@ -181,4 +182,16 @@ protected void processBean(
181182
}
182183
}
183184

185+
186+
/**
187+
* Determine whether the given class is an {@code org.springframework}
188+
* bean class that is not annotated as a user or test {@link Component}...
189+
* which indicates that there is no {@link EventListener} to be found there.
190+
* @since 5.1
191+
*/
192+
private static boolean isSpringContainerClass(Class<?> clazz) {
193+
return (clazz.getName().startsWith("org.springframework.") &&
194+
!AnnotatedElementUtils.isAnnotated(clazz, Component.class));
195+
}
196+
184197
}

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ public static boolean hasMetaAnnotationTypes(AnnotatedElement element, String an
228228
return hasMetaAnnotationTypes(element, null, annotationName);
229229
}
230230

231-
private static boolean hasMetaAnnotationTypes(AnnotatedElement element, @Nullable Class<? extends Annotation> annotationType,
232-
@Nullable String annotationName) {
231+
private static boolean hasMetaAnnotationTypes(
232+
AnnotatedElement element, @Nullable Class<? extends Annotation> annotationType, @Nullable String annotationName) {
233233

234234
return Boolean.TRUE.equals(
235235
searchWithGetSemantics(element, annotationType, annotationName, new SimpleAnnotationProcessor<Boolean>() {
@@ -680,6 +680,11 @@ public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement ele
680680
}
681681
}
682682

683+
// Shortcut: no non-java annotations to be found on plain Java classes and org.springframework.lang types...
684+
if (AnnotationUtils.hasPlainJavaAnnotationsOnly(element) && !annotationType.getName().startsWith("java")) {
685+
return null;
686+
}
687+
683688
// Exhaustive retrieval of merged annotation attributes...
684689
AnnotationAttributes attributes = findMergedAnnotationAttributes(element, annotationType, false, false);
685690
return (attributes != null ? AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element) : null);
@@ -1007,7 +1012,7 @@ private static <T> T searchWithFindSemantics(AnnotatedElement element,
10071012

10081013
if (containerType != null && !processor.aggregates()) {
10091014
throw new IllegalArgumentException(
1010-
"Searches for repeatable annotations must supply an aggregating Processor");
1015+
"Searches for repeatable annotations must supply an aggregating Processor");
10111016
}
10121017

10131018
try {

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -641,11 +641,13 @@ private static boolean hasSearchableAnnotations(Method ifcMethod) {
641641
if (anns.length == 0) {
642642
return false;
643643
}
644-
if (anns.length == 1) {
645-
Class<?> annType = anns[0].annotationType();
646-
return (annType != Nullable.class && annType != Deprecated.class);
644+
for (Annotation ann : anns) {
645+
String name = ann.annotationType().getName();
646+
if (!name.startsWith("java.lang.") && !name.startsWith("org.springframework.lang.")) {
647+
return true;
648+
}
647649
}
648-
return true;
650+
return false;
649651
}
650652

651653
private static boolean isOverride(Method method, Method candidate) {
@@ -920,11 +922,11 @@ public static boolean isAnnotationMetaPresent(Class<? extends Annotation> annota
920922
}
921923

922924
/**
923-
* Determine if the {@link Annotation} with the supplied name is defined in the
924-
* {@code java.lang.annotation} or {@code org.springframework.lang} package.
925-
* @param annotatedElement the potential annotation type to check
926-
* @return {@code true} if the annotation is in the {@code java.lang.annotation}
927-
* or {@code org.springframework.lang} package
925+
* Determine if the given annotated element is defined in a
926+
* {@code java} or in the {@code org.springframework.lang} package.
927+
* @param annotatedElement the annotated element to check
928+
* @return {@code true} if the given element is in a {@code java}
929+
* package or in the {@code org.springframework.lang} package
928930
* @since 5.1
929931
*/
930932
static boolean hasPlainJavaAnnotationsOnly(@Nullable Object annotatedElement) {

0 commit comments

Comments
 (0)