Fix bug in StaticListableBeanFactory.isSingleton()
Prior to this commit, StaticListableBeanFactory.isSingleton() returned false for singleton beans unless they were created by a FactoryBean. StaticListableBeanFactory.isSingleton() now properly returns true for all beans not created by a FactoryBean. Closes gh-25522
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -40,20 +40,22 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Static {@link org.springframework.beans.factory.BeanFactory} implementation
|
||||
* which allows to register existing singleton instances programmatically.
|
||||
* Does not have support for prototype beans or aliases.
|
||||
* which allows one to register existing singleton instances programmatically.
|
||||
*
|
||||
* <p>Serves as example for a simple implementation of the
|
||||
* <p>Does not have support for prototype beans or aliases.
|
||||
*
|
||||
* <p>Serves as an example for a simple implementation of the
|
||||
* {@link org.springframework.beans.factory.ListableBeanFactory} interface,
|
||||
* managing existing bean instances rather than creating new ones based on bean
|
||||
* definitions, and not implementing any extended SPI interfaces (such as
|
||||
* {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}).
|
||||
*
|
||||
* <p>For a full-fledged factory based on bean definitions, have a look
|
||||
* at {@link DefaultListableBeanFactory}.
|
||||
* <p>For a full-fledged factory based on bean definitions, have a look at
|
||||
* {@link DefaultListableBeanFactory}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 06.01.2003
|
||||
* @see DefaultListableBeanFactory
|
||||
*/
|
||||
@@ -78,7 +80,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
* or {@link java.util.Collections#emptyMap()} for a dummy factory which
|
||||
* enforces operating against an empty set of beans.
|
||||
* @param beans a {@code Map} for holding this factory's beans, with the
|
||||
* bean name String as key and the corresponding singleton object as value
|
||||
* bean name as key and the corresponding singleton object as value
|
||||
* @since 4.3
|
||||
*/
|
||||
public StaticListableBeanFactory(Map<String, Object> beans) {
|
||||
@@ -89,7 +91,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
|
||||
/**
|
||||
* Add a new singleton bean.
|
||||
* Will overwrite any existing instance for the given name.
|
||||
* <p>Will overwrite any existing instance for the given name.
|
||||
* @param name the name of the bean
|
||||
* @param bean the bean instance
|
||||
*/
|
||||
@@ -182,7 +184,10 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
|
||||
Object bean = getBean(name);
|
||||
// In case of FactoryBean, return singleton status of created object.
|
||||
return (bean instanceof FactoryBean && ((FactoryBean<?>) bean).isSingleton());
|
||||
if (bean instanceof FactoryBean) {
|
||||
return ((FactoryBean<?>) bean).isSingleton();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2020 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 static org.springframework.tests.TestResourceUtils.*;
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @author Sam Brannen
|
||||
* @since 04.07.2003
|
||||
*/
|
||||
public final class BeanFactoryUtilsTests {
|
||||
@@ -289,4 +290,111 @@ public final class BeanFactoryUtilsTests {
|
||||
assertTrue(Arrays.equals(new String[] { "buffer" }, deps));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSingletonAndIsPrototypeWithStaticFactory() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
TestBean bean = new TestBean();
|
||||
DummyFactory fb1 = new DummyFactory();
|
||||
DummyFactory fb2 = new DummyFactory();
|
||||
fb2.setSingleton(false);
|
||||
TestBeanSmartFactoryBean sfb1 = new TestBeanSmartFactoryBean(true, true);
|
||||
TestBeanSmartFactoryBean sfb2 = new TestBeanSmartFactoryBean(true, false);
|
||||
TestBeanSmartFactoryBean sfb3 = new TestBeanSmartFactoryBean(false, true);
|
||||
TestBeanSmartFactoryBean sfb4 = new TestBeanSmartFactoryBean(false, false);
|
||||
lbf.addBean("bean", bean);
|
||||
lbf.addBean("fb1", fb1);
|
||||
lbf.addBean("fb2", fb2);
|
||||
lbf.addBean("sfb1", sfb1);
|
||||
lbf.addBean("sfb2", sfb2);
|
||||
lbf.addBean("sfb3", sfb3);
|
||||
lbf.addBean("sfb4", sfb4);
|
||||
|
||||
Map<String, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, true);
|
||||
assertSame(bean, beans.get("bean"));
|
||||
assertSame(fb1.getObject(), beans.get("fb1"));
|
||||
assertTrue(beans.get("fb2") instanceof TestBean);
|
||||
assertTrue(beans.get("sfb1") instanceof TestBean);
|
||||
assertTrue(beans.get("sfb2") instanceof TestBean);
|
||||
assertTrue(beans.get("sfb3") instanceof TestBean);
|
||||
assertTrue(beans.get("sfb4") instanceof TestBean);
|
||||
|
||||
assertEquals(7, lbf.getBeanDefinitionCount());
|
||||
assertTrue(lbf.getBean("bean") instanceof TestBean);
|
||||
assertTrue(lbf.getBean("&fb1") instanceof FactoryBean);
|
||||
assertTrue(lbf.getBean("&fb2") instanceof FactoryBean);
|
||||
assertTrue(lbf.getBean("&sfb1") instanceof SmartFactoryBean);
|
||||
assertTrue(lbf.getBean("&sfb2") instanceof SmartFactoryBean);
|
||||
assertTrue(lbf.getBean("&sfb3") instanceof SmartFactoryBean);
|
||||
assertTrue(lbf.getBean("&sfb4") instanceof SmartFactoryBean);
|
||||
|
||||
assertTrue(lbf.isSingleton("bean"));
|
||||
assertTrue(lbf.isSingleton("fb1"));
|
||||
assertTrue(lbf.isSingleton("fb2"));
|
||||
assertTrue(lbf.isSingleton("sfb1"));
|
||||
assertTrue(lbf.isSingleton("sfb2"));
|
||||
assertTrue(lbf.isSingleton("sfb3"));
|
||||
assertTrue(lbf.isSingleton("sfb4"));
|
||||
|
||||
assertTrue(lbf.isSingleton("&fb1"));
|
||||
assertFalse(lbf.isSingleton("&fb2"));
|
||||
assertTrue(lbf.isSingleton("&sfb1"));
|
||||
assertTrue(lbf.isSingleton("&sfb2"));
|
||||
assertFalse(lbf.isSingleton("&sfb3"));
|
||||
assertFalse(lbf.isSingleton("&sfb4"));
|
||||
|
||||
assertFalse(lbf.isPrototype("bean"));
|
||||
assertFalse(lbf.isPrototype("fb1"));
|
||||
assertFalse(lbf.isPrototype("fb2"));
|
||||
assertFalse(lbf.isPrototype("sfb1"));
|
||||
assertFalse(lbf.isPrototype("sfb2"));
|
||||
assertFalse(lbf.isPrototype("sfb3"));
|
||||
assertFalse(lbf.isPrototype("sfb4"));
|
||||
|
||||
assertFalse(lbf.isPrototype("&fb1"));
|
||||
assertTrue(lbf.isPrototype("&fb2"));
|
||||
assertTrue(lbf.isPrototype("&sfb1"));
|
||||
assertFalse(lbf.isPrototype("&sfb2"));
|
||||
assertTrue(lbf.isPrototype("&sfb3"));
|
||||
assertTrue(lbf.isPrototype("&sfb4"));
|
||||
}
|
||||
|
||||
|
||||
static class TestBeanSmartFactoryBean implements SmartFactoryBean<TestBean> {
|
||||
|
||||
private final TestBean testBean = new TestBean("enigma", 42);
|
||||
private final boolean singleton;
|
||||
private final boolean prototype;
|
||||
|
||||
TestBeanSmartFactoryBean(boolean singleton, boolean prototype) {
|
||||
this.singleton = singleton;
|
||||
this.prototype = prototype;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return this.singleton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrototype() {
|
||||
return this.prototype;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEagerInit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<TestBean> getObjectType() {
|
||||
return TestBean.class;
|
||||
}
|
||||
|
||||
public TestBean getObject() throws Exception {
|
||||
// We don't really care if the actual instance is a singleton or prototype
|
||||
// for the tests that use this factory.
|
||||
return this.testBean;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user