diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java index 517cf92b237d..189b2b1386bb 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java @@ -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; } } @@ -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] && @@ -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)); } diff --git a/spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java b/spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java index d914df5ff41c..6df761728b1c 100644 --- a/spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java @@ -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. @@ -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; @@ -137,7 +138,7 @@ protected List getEventListenerFactories() { protected void processBean( final List factories, final String beanName, final Class targetType) { - if (!this.nonAnnotatedClasses.contains(targetType)) { + if (!this.nonAnnotatedClasses.contains(targetType) && !isSpringContainerClass(targetType)) { Map annotatedMethods = null; try { annotatedMethods = MethodIntrospector.selectMethods(targetType, @@ -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)); + } + } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java index 6097fbfb8a67..a68ade2dba2e 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java @@ -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 annotationType, - @Nullable String annotationName) { + private static boolean hasMetaAnnotationTypes( + AnnotatedElement element, @Nullable Class annotationType, @Nullable String annotationName) { return Boolean.TRUE.equals( searchWithGetSemantics(element, annotationType, annotationName, new SimpleAnnotationProcessor() { @@ -680,6 +680,11 @@ public static 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); @@ -1007,7 +1012,7 @@ private static 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 { diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index ab0074954f3d..c0981e1bc452 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -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) { @@ -920,11 +922,11 @@ public static boolean isAnnotationMetaPresent(Class 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) {