Skip to content

Commit

Permalink
Avoid unnecessary annotation introspection on framework methods
Browse files Browse the repository at this point in the history
Issue: SPR-16933
  • Loading branch information
jhoeller committed Aug 6, 2018
1 parent f155d21 commit d72d376
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ public ConditionalCallbackFilter(Callback[] callbacks) {
@Override
public int accept(Method method) {
for (int i = 0; i < this.callbacks.length; i++) {
if (!(this.callbacks[i] instanceof ConditionalCallback) ||
((ConditionalCallback) this.callbacks[i]).isMatch(method)) {
Callback callback = this.callbacks[i];
if (!(callback instanceof ConditionalCallback) || ((ConditionalCallback) callback).isMatch(method)) {
return i;
}
}
Expand Down Expand Up @@ -285,6 +285,10 @@ public Object intercept(Object obj, Method method, Object[] args, MethodProxy pr

@Override
public boolean isMatch(Method candidateMethod) {
return isSetBeanFactory(candidateMethod);
}

public static boolean isSetBeanFactory(Method candidateMethod) {
return (candidateMethod.getName().equals("setBeanFactory") &&
candidateMethod.getParameterCount() == 1 &&
BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
Expand Down Expand Up @@ -430,6 +434,7 @@ private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
@Override
public boolean isMatch(Method candidateMethod) {
return (candidateMethod.getDeclaringClass() != Object.class &&
!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -41,6 +41,7 @@
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

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

if (!this.nonAnnotatedClasses.contains(targetType)) {
if (!this.nonAnnotatedClasses.contains(targetType) && !isSpringContainerClass(targetType)) {
Map<Method, EventListener> annotatedMethods = null;
try {
annotatedMethods = MethodIntrospector.selectMethods(targetType,
Expand Down Expand Up @@ -181,4 +182,16 @@ protected void processBean(
}
}


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

}
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ public static boolean hasMetaAnnotationTypes(AnnotatedElement element, String an
return hasMetaAnnotationTypes(element, null, annotationName);
}

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

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

// Shortcut: no non-java annotations to be found on plain Java classes and org.springframework.lang types...
if (AnnotationUtils.hasPlainJavaAnnotationsOnly(element) && !annotationType.getName().startsWith("java")) {
return null;
}

// Exhaustive retrieval of merged annotation attributes...
AnnotationAttributes attributes = findMergedAnnotationAttributes(element, annotationType, false, false);
return (attributes != null ? AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element) : null);
Expand Down Expand Up @@ -1007,7 +1012,7 @@ private static <T> T searchWithFindSemantics(AnnotatedElement element,

if (containerType != null && !processor.aggregates()) {
throw new IllegalArgumentException(
"Searches for repeatable annotations must supply an aggregating Processor");
"Searches for repeatable annotations must supply an aggregating Processor");
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,11 +641,13 @@ private static boolean hasSearchableAnnotations(Method ifcMethod) {
if (anns.length == 0) {
return false;
}
if (anns.length == 1) {
Class<?> annType = anns[0].annotationType();
return (annType != Nullable.class && annType != Deprecated.class);
for (Annotation ann : anns) {
String name = ann.annotationType().getName();
if (!name.startsWith("java.lang.") && !name.startsWith("org.springframework.lang.")) {
return true;
}
}
return true;
return false;
}

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

/**
* Determine if the {@link Annotation} with the supplied name is defined in the
* {@code java.lang.annotation} or {@code org.springframework.lang} package.
* @param annotatedElement the potential annotation type to check
* @return {@code true} if the annotation is in the {@code java.lang.annotation}
* or {@code org.springframework.lang} package
* Determine if the given annotated element is defined in a
* {@code java} or in the {@code org.springframework.lang} package.
* @param annotatedElement the annotated element to check
* @return {@code true} if the given element is in a {@code java}
* package or in the {@code org.springframework.lang} package
* @since 5.1
*/
static boolean hasPlainJavaAnnotationsOnly(@Nullable Object annotatedElement) {
Expand Down

0 comments on commit d72d376

Please sign in to comment.