Detect factory method annotations in getBeanNamesForAnnotation and co
As of 5.2, ListableBeanFactory.findAnnotationOnBean and its retrieval companions getBeanNamesForAnnotation and getBeansWithAnnotation detect annotations on @Bean methods as well. Closes gh-22541
This commit is contained in:
@@ -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 {
|
||||
* <p>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 {
|
||||
* <p>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<String, Object> 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 extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||
|
||||
@@ -678,23 +678,32 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
Class<?> beanType = getType(beanName);
|
||||
if (beanType != null) {
|
||||
MergedAnnotation<A> annotation = MergedAnnotations.from(beanType,
|
||||
SearchStrategy.EXHAUSTIVE).get(annotationType);
|
||||
MergedAnnotation<A> 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<A> annotation =
|
||||
MergedAnnotations.from(beanClass, SearchStrategy.EXHAUSTIVE).get(annotationType);
|
||||
if (annotation.isPresent()) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
Method factoryMethod = bd.getResolvedFactoryMethod();
|
||||
if (factoryMethod != null) {
|
||||
MergedAnnotation<A> 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<Object> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user