diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
index 62c6e2b10d6..f2122b2f789 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/ListableBeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -248,8 +248,10 @@ public interface ListableBeanFactory extends BeanFactory {
*
Note that this method considers objects created by FactoryBeans, which means
* that FactoryBeans will get initialized in order to determine their object type.
* @param annotationType the type of annotation to look for
+ * (at class, interface or factory method level of the specified bean)
* @return the names of all matching beans
* @since 4.0
+ * @see #findAnnotationOnBean
*/
String[] getBeanNamesForAnnotation(Class extends Annotation> annotationType);
@@ -259,22 +261,27 @@ public interface ListableBeanFactory extends BeanFactory {
*
Note that this method considers objects created by FactoryBeans, which means
* that FactoryBeans will get initialized in order to determine their object type.
* @param annotationType the type of annotation to look for
+ * (at class, interface or factory method level of the specified bean)
* @return a Map with the matching beans, containing the bean names as
* keys and the corresponding bean instances as values
* @throws BeansException if a bean could not be created
* @since 3.0
+ * @see #findAnnotationOnBean
*/
Map getBeansWithAnnotation(Class extends Annotation> annotationType) throws BeansException;
/**
- * Find an {@link Annotation} of {@code annotationType} on the specified
- * bean, traversing its interfaces and super classes if no annotation can be
- * found on the given class itself.
+ * Find an {@link Annotation} of {@code annotationType} on the specified bean,
+ * traversing its interfaces and super classes if no annotation can be found on
+ * the given class itself, as well as checking the bean's factory method (if any).
* @param beanName the name of the bean to look for annotations on
- * @param annotationType the annotation class to look for
+ * @param annotationType the type of annotation to look for
+ * (at class, interface or factory method level of the specified bean)
* @return the annotation of the given type if found, or {@code null} otherwise
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 3.0
+ * @see #getBeanNamesForAnnotation
+ * @see #getBeansWithAnnotation
*/
@Nullable
A findAnnotationOnBean(String beanName, Class annotationType)
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
index e916ab7121e..09a8c31c445 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
@@ -678,23 +678,32 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Class> beanType = getType(beanName);
if (beanType != null) {
- MergedAnnotation annotation = MergedAnnotations.from(beanType,
- SearchStrategy.EXHAUSTIVE).get(annotationType);
+ MergedAnnotation annotation =
+ MergedAnnotations.from(beanType, SearchStrategy.EXHAUSTIVE).get(annotationType);
if (annotation.isPresent()) {
return annotation;
}
}
if (containsBeanDefinition(beanName)) {
- BeanDefinition bd = getMergedBeanDefinition(beanName);
- if (bd instanceof AbstractBeanDefinition) {
- AbstractBeanDefinition abd = (AbstractBeanDefinition) bd;
- if (abd.hasBeanClass()) {
- Class> beanClass = abd.getBeanClass();
- if (beanClass != beanType) {
- return MergedAnnotations.from(beanClass, SearchStrategy.EXHAUSTIVE).get(annotationType);
+ RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
+ if (bd.hasBeanClass()) {
+ Class> beanClass = bd.getBeanClass();
+ if (beanClass != beanType) {
+ MergedAnnotation annotation =
+ MergedAnnotations.from(beanClass, SearchStrategy.EXHAUSTIVE).get(annotationType);
+ if (annotation.isPresent()) {
+ return annotation;
}
}
}
+ Method factoryMethod = bd.getResolvedFactoryMethod();
+ if (factoryMethod != null) {
+ MergedAnnotation annotation =
+ MergedAnnotations.from(factoryMethod, SearchStrategy.EXHAUSTIVE).get(annotationType);
+ if (annotation.isPresent()) {
+ return annotation;
+ }
+ }
}
return MergedAnnotation.missing();
}
@@ -1988,10 +1997,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
@Nullable
public Object getOrderSource(Object obj) {
- RootBeanDefinition beanDefinition = getRootBeanDefinition(this.instancesToBeanNames.get(obj));
- if (beanDefinition == null) {
+ String beanName = this.instancesToBeanNames.get(obj);
+ if (beanName == null || !containsBeanDefinition(beanName)) {
return null;
}
+ RootBeanDefinition beanDefinition = getMergedLocalBeanDefinition(beanName);
List sources = new ArrayList<>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
@@ -2003,17 +2013,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
return sources.toArray();
}
-
- @Nullable
- private RootBeanDefinition getRootBeanDefinition(@Nullable String beanName) {
- if (beanName != null && containsBeanDefinition(beanName)) {
- BeanDefinition bd = getMergedBeanDefinition(beanName);
- if (bd instanceof RootBeanDefinition) {
- return (RootBeanDefinition) bd;
- }
- }
- return null;
- }
}
}
diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/BeanMethodQualificationTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/BeanMethodQualificationTests.java
index a067a4e83c5..bc7b2eff912 100644
--- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/BeanMethodQualificationTests.java
+++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/BeanMethodQualificationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -129,6 +129,16 @@ public class BeanMethodQualificationTests {
assertThat(pojo.testBean.getName(), equalTo("interesting"));
}
+ @Test
+ public void testBeanNamesForAnnotation() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(StandardConfig.class);
+ assertArrayEquals(new String[] {"beanMethodQualificationTests.StandardConfig"},
+ ctx.getBeanNamesForAnnotation(Configuration.class));
+ assertArrayEquals(new String[] {}, ctx.getBeanNamesForAnnotation(Scope.class));
+ assertArrayEquals(new String[] {"testBean1"}, ctx.getBeanNamesForAnnotation(Lazy.class));
+ assertArrayEquals(new String[] {"testBean2"}, ctx.getBeanNamesForAnnotation(Boring.class));
+ }
+
@Configuration
static class StandardConfig {