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 389f19c9e48..2642e72d7ae 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-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -353,9 +353,31 @@ public interface ListableBeanFactory extends BeanFactory { * @since 3.0 * @see #getBeanNamesForAnnotation * @see #getBeansWithAnnotation + * @see #getType(String) */ @Nullable A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException; + /** + * 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 type of annotation to look for + * (at class, interface or factory method level of the specified bean) + * @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized + * just for the purpose of determining its object type + * @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 5.3.14 + * @see #getBeanNamesForAnnotation + * @see #getBeansWithAnnotation + * @see #getType(String, boolean) + */ + @Nullable + A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException; + } 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 048612fbed7..b019ef5361f 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -730,14 +730,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto public A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException { - return findMergedAnnotationOnBean(beanName, annotationType) + return findAnnotationOnBean(beanName, annotationType, true); + } + + @Override + @Nullable + public A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException { + + return findMergedAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit) .synthesize(MergedAnnotation::isPresent).orElse(null); } private MergedAnnotation findMergedAnnotationOnBean( - String beanName, Class annotationType) { + String beanName, Class annotationType, boolean allowFactoryBeanInit) { - Class beanType = getType(beanName); + Class beanType = getType(beanName, allowFactoryBeanInit); if (beanType != null) { MergedAnnotation annotation = MergedAnnotations.from(beanType, SearchStrategy.TYPE_HIERARCHY).get(annotationType); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java index a5430120dfd..1105ead3e12 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -459,7 +459,16 @@ public class StaticListableBeanFactory implements ListableBeanFactory { public A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException { - Class beanType = getType(beanName); + return findAnnotationOnBean(beanName, annotationType, true); + } + + @Override + @Nullable + public A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException { + + Class beanType = getType(beanName, allowFactoryBeanInit); return (beanType != null ? AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType) : null); } diff --git a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java index aca706e82c1..38243b17944 100644 --- a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java +++ b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java @@ -1331,6 +1331,16 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader return getBeanFactory().findAnnotationOnBean(beanName, annotationType); } + @Override + @Nullable + public A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException { + + assertBeanFactoryActive(); + return getBeanFactory().findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit); + } + //--------------------------------------------------------------------- // Implementation of HierarchicalBeanFactory interface diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java index c5271e8d18e..4a64b49d994 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -314,6 +314,15 @@ class StubWebApplicationContext implements WebApplicationContext { return this.beanFactory.findAnnotationOnBean(beanName, annotationType); } + @Override + @Nullable + public A findAnnotationOnBean( + String beanName, Class annotationType, boolean allowFactoryBeanInit) + throws NoSuchBeanDefinitionException { + + return this.beanFactory.findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit); + } + //--------------------------------------------------------------------- // Implementation of HierarchicalBeanFactory interface