Fix inconsistencies in StaticListableBeanFactory
Backport Bot / build (push) Has been cancelled Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled Details
Deploy Docs / Dispatch docs deployment (push) Has been cancelled Details
Build and Deploy Snapshot / Verify (push) Has been cancelled Details

Closes gh-35119
This commit is contained in:
Juergen Hoeller 2025-06-27 12:28:52 +02:00
parent 511739e3de
commit bd72f1fefc
3 changed files with 47 additions and 53 deletions

View File

@ -2701,7 +2701,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return null; return null;
} }
try { try {
RootBeanDefinition beanDefinition = (RootBeanDefinition) getMergedBeanDefinition(beanName); BeanDefinition beanDefinition = getMergedBeanDefinition(beanName);
List<Object> sources = new ArrayList<>(3); List<Object> sources = new ArrayList<>(3);
Object orderAttribute = beanDefinition.getAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE); Object orderAttribute = beanDefinition.getAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE);
if (orderAttribute != null) { if (orderAttribute != null) {
@ -2713,14 +2713,16 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
AbstractBeanDefinition.ORDER_ATTRIBUTE + "': " + orderAttribute.getClass().getName()); AbstractBeanDefinition.ORDER_ATTRIBUTE + "': " + orderAttribute.getClass().getName());
} }
} }
Method factoryMethod = beanDefinition.getResolvedFactoryMethod(); if (beanDefinition instanceof RootBeanDefinition rootBeanDefinition) {
Method factoryMethod = rootBeanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) { if (factoryMethod != null) {
sources.add(factoryMethod); sources.add(factoryMethod);
} }
Class<?> targetType = beanDefinition.getTargetType(); Class<?> targetType = rootBeanDefinition.getTargetType();
if (targetType != null && targetType != obj.getClass()) { if (targetType != null && targetType != obj.getClass()) {
sources.add(targetType); sources.add(targetType);
} }
}
return sources.toArray(); return sources.toArray();
} }
catch (NoSuchBeanDefinitionException ex) { catch (NoSuchBeanDefinitionException ex) {

View File

@ -113,15 +113,8 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
@Override @Override
public Object getBean(String name) throws BeansException { public Object getBean(String name) throws BeansException {
String beanName = BeanFactoryUtils.transformedBeanName(name); String beanName = BeanFactoryUtils.transformedBeanName(name);
Object bean = this.beans.get(beanName); Object bean = obtainBean(beanName);
if (bean == null) {
throw new NoSuchBeanDefinitionException(beanName,
"Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
}
// Don't let calling code try to dereference the
// bean factory if the bean isn't a factory
if (BeanFactoryUtils.isFactoryDereference(name) && !(bean instanceof FactoryBean)) { if (BeanFactoryUtils.isFactoryDereference(name) && !(bean instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, bean.getClass()); throw new BeanIsNotAFactoryException(beanName, bean.getClass());
} }
@ -162,6 +155,15 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
return getBean(name); return getBean(name);
} }
private Object obtainBean(String beanName) {
Object bean = this.beans.get(beanName);
if (bean == null) {
throw new NoSuchBeanDefinitionException(beanName,
"Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
}
return bean;
}
@Override @Override
public <T> T getBean(Class<T> requiredType) throws BeansException { public <T> T getBean(Class<T> requiredType) throws BeansException {
String[] beanNames = getBeanNamesForType(requiredType); String[] beanNames = getBeanNamesForType(requiredType);
@ -202,9 +204,9 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
@Override @Override
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
Object bean = getBean(name); String beanName = BeanFactoryUtils.transformedBeanName(name);
// In case of FactoryBean, return singleton status of created object. Object bean = obtainBean(beanName);
if (bean instanceof FactoryBean<?> factoryBean) { if (bean instanceof FactoryBean<?> factoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
return factoryBean.isSingleton(); return factoryBean.isSingleton();
} }
return true; return true;
@ -212,10 +214,11 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
@Override @Override
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException { public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
Object bean = getBean(name); String beanName = BeanFactoryUtils.transformedBeanName(name);
// In case of FactoryBean, return prototype status of created object. Object bean = obtainBean(beanName);
return ((bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isPrototype()) || return (!BeanFactoryUtils.isFactoryDereference(name) &&
(bean instanceof FactoryBean<?> factoryBean && !factoryBean.isSingleton())); ((bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isPrototype()) ||
(bean instanceof FactoryBean<?> factoryBean && !factoryBean.isSingleton())));
} }
@Override @Override
@ -240,15 +243,8 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
@Nullable @Nullable
public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException { public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
String beanName = BeanFactoryUtils.transformedBeanName(name); String beanName = BeanFactoryUtils.transformedBeanName(name);
Object bean = obtainBean(beanName);
Object bean = this.beans.get(beanName);
if (bean == null) {
throw new NoSuchBeanDefinitionException(beanName,
"Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
}
if (bean instanceof FactoryBean<?> factoryBean && !BeanFactoryUtils.isFactoryDereference(name)) { if (bean instanceof FactoryBean<?> factoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
return factoryBean.getObjectType(); return factoryBean.getObjectType();
} }
return bean.getClass(); return bean.getClass();
@ -292,7 +288,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
public T getObject() throws BeansException { public T getObject() throws BeansException {
String[] beanNames = getBeanNamesForType(requiredType); String[] beanNames = getBeanNamesForType(requiredType);
if (beanNames.length == 1) { if (beanNames.length == 1) {
return (T) getBean(beanNames[0], requiredType); return (T) getBean(beanNames[0]);
} }
else if (beanNames.length > 1) { else if (beanNames.length > 1) {
throw new NoUniqueBeanDefinitionException(requiredType, beanNames); throw new NoUniqueBeanDefinitionException(requiredType, beanNames);
@ -356,7 +352,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
boolean includeNonSingletons, boolean allowEagerInit) { boolean includeNonSingletons, boolean allowEagerInit) {
Class<?> resolved = (type != null ? type.resolve() : null); Class<?> resolved = (type != null ? type.resolve() : null);
boolean isFactoryType = resolved != null && FactoryBean.class.isAssignableFrom(resolved); boolean isFactoryType = (resolved != null && FactoryBean.class.isAssignableFrom(resolved));
List<String> matches = new ArrayList<>(); List<String> matches = new ArrayList<>();
for (Map.Entry<String, Object> entry : this.beans.entrySet()) { for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
@ -365,7 +361,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
if (beanInstance instanceof FactoryBean<?> factoryBean && !isFactoryType) { if (beanInstance instanceof FactoryBean<?> factoryBean && !isFactoryType) {
Class<?> objectType = factoryBean.getObjectType(); Class<?> objectType = factoryBean.getObjectType();
if ((includeNonSingletons || factoryBean.isSingleton()) && if ((includeNonSingletons || factoryBean.isSingleton()) &&
objectType != null && (type == null || type.isAssignableFrom(objectType))) { (type == null || (objectType != null && type.isAssignableFrom(objectType)))) {
matches.add(beanName); matches.add(beanName);
} }
} }
@ -404,19 +400,15 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
for (Map.Entry<String, Object> entry : this.beans.entrySet()) { for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
String beanName = entry.getKey(); String beanName = entry.getKey();
Object beanInstance = entry.getValue(); Object beanInstance = entry.getValue();
// Is bean a FactoryBean?
if (beanInstance instanceof FactoryBean<?> factoryBean && !isFactoryType) { if (beanInstance instanceof FactoryBean<?> factoryBean && !isFactoryType) {
// Match object created by FactoryBean.
Class<?> objectType = factoryBean.getObjectType(); Class<?> objectType = factoryBean.getObjectType();
if ((includeNonSingletons || factoryBean.isSingleton()) && if ((includeNonSingletons || factoryBean.isSingleton()) &&
objectType != null && (type == null || type.isAssignableFrom(objectType))) { (type == null || (objectType != null && type.isAssignableFrom(objectType)))) {
matches.put(beanName, getBean(beanName, type)); matches.put(beanName, getBean(beanName, type));
} }
} }
else { else {
if (type == null || type.isInstance(beanInstance)) { if (type == null || type.isInstance(beanInstance)) {
// If type to match is FactoryBean, return FactoryBean itself.
// Else, return bean instance.
if (isFactoryType) { if (isFactoryType) {
beanName = FACTORY_BEAN_PREFIX + beanName; beanName = FACTORY_BEAN_PREFIX + beanName;
} }

View File

@ -388,33 +388,33 @@ class BeanFactoryUtilsTests {
assertThat(lbf.isSingleton("bean")).isTrue(); assertThat(lbf.isSingleton("bean")).isTrue();
assertThat(lbf.isSingleton("fb1")).isTrue(); assertThat(lbf.isSingleton("fb1")).isTrue();
assertThat(lbf.isSingleton("fb2")).isTrue(); assertThat(lbf.isSingleton("fb2")).isFalse();
assertThat(lbf.isSingleton("sfb1")).isTrue(); assertThat(lbf.isSingleton("sfb1")).isTrue();
assertThat(lbf.isSingleton("sfb2")).isTrue(); assertThat(lbf.isSingleton("sfb2")).isTrue();
assertThat(lbf.isSingleton("sfb3")).isTrue(); assertThat(lbf.isSingleton("sfb3")).isFalse();
assertThat(lbf.isSingleton("sfb4")).isTrue(); assertThat(lbf.isSingleton("sfb4")).isFalse();
assertThat(lbf.isSingleton("&fb1")).isTrue(); assertThat(lbf.isSingleton("&fb1")).isTrue();
assertThat(lbf.isSingleton("&fb2")).isFalse(); assertThat(lbf.isSingleton("&fb2")).isTrue();
assertThat(lbf.isSingleton("&sfb1")).isTrue(); assertThat(lbf.isSingleton("&sfb1")).isTrue();
assertThat(lbf.isSingleton("&sfb2")).isTrue(); assertThat(lbf.isSingleton("&sfb2")).isTrue();
assertThat(lbf.isSingleton("&sfb3")).isFalse(); assertThat(lbf.isSingleton("&sfb3")).isTrue();
assertThat(lbf.isSingleton("&sfb4")).isFalse(); assertThat(lbf.isSingleton("&sfb4")).isTrue();
assertThat(lbf.isPrototype("bean")).isFalse(); assertThat(lbf.isPrototype("bean")).isFalse();
assertThat(lbf.isPrototype("fb1")).isFalse(); assertThat(lbf.isPrototype("fb1")).isFalse();
assertThat(lbf.isPrototype("fb2")).isFalse(); assertThat(lbf.isPrototype("fb2")).isTrue();
assertThat(lbf.isPrototype("sfb1")).isFalse(); assertThat(lbf.isPrototype("sfb1")).isTrue();
assertThat(lbf.isPrototype("sfb2")).isFalse(); assertThat(lbf.isPrototype("sfb2")).isFalse();
assertThat(lbf.isPrototype("sfb3")).isFalse(); assertThat(lbf.isPrototype("sfb3")).isTrue();
assertThat(lbf.isPrototype("sfb4")).isFalse(); assertThat(lbf.isPrototype("sfb4")).isTrue();
assertThat(lbf.isPrototype("&fb1")).isFalse(); assertThat(lbf.isPrototype("&fb1")).isFalse();
assertThat(lbf.isPrototype("&fb2")).isTrue(); assertThat(lbf.isPrototype("&fb2")).isFalse();
assertThat(lbf.isPrototype("&sfb1")).isTrue(); assertThat(lbf.isPrototype("&sfb1")).isFalse();
assertThat(lbf.isPrototype("&sfb2")).isFalse(); assertThat(lbf.isPrototype("&sfb2")).isFalse();
assertThat(lbf.isPrototype("&sfb3")).isTrue(); assertThat(lbf.isPrototype("&sfb3")).isFalse();
assertThat(lbf.isPrototype("&sfb4")).isTrue(); assertThat(lbf.isPrototype("&sfb4")).isFalse();
} }