From b41e3956bcbefb4c00f92e6d8f9afe98f80d7181 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 19 Nov 2009 18:32:10 +0000 Subject: [PATCH] revised scope inheritance: default scope is "" (empty String) now; consistent isPrototype checks --- .../beans/factory/config/BeanDefinition.java | 8 +++++ .../AbstractAutowireCapableBeanFactory.java | 2 +- .../support/AbstractBeanDefinition.java | 31 +++++++++++++------ .../factory/support/AbstractBeanFactory.java | 2 +- .../beans/factory/xml/spring-beans-3.0.xsd | 7 ++--- 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java index 05b9769666..f18fa848b3 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java @@ -211,9 +211,17 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { /** * Return whether this a Singleton, with a single, shared instance * returned on all calls. + * @see #SCOPE_SINGLETON */ boolean isSingleton(); + /** + * Return whether this a Prototype, with an independent instance + * returned for each call. + * @see #SCOPE_PROTOTYPE + */ + boolean isPrototype(); + /** * Return whether this bean is "abstract", that is, not meant to be instantiated. */ diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 7728c939f4..e45ad9526e 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -301,7 +301,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac RootBeanDefinition bd = null; if (mbd instanceof RootBeanDefinition) { RootBeanDefinition rbd = (RootBeanDefinition) mbd; - if (SCOPE_PROTOTYPE.equals(rbd.getScope())) { + if (rbd.isPrototype()) { bd = rbd; } } diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java index 13b33165b1..e7c98618ec 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java @@ -33,6 +33,7 @@ import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; /** * Base class for concrete, full-fledged @@ -54,6 +55,13 @@ import org.springframework.util.ObjectUtils; public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { + /** + * Constant for the default scope name: "", equivalent to singleton status + * but to be overridden from a parent bean definition (if applicable). + */ + public static final String SCOPE_DEFAULT = ""; + + /** * Constant that indicates no autowiring at all. * @see #setAutowireMode @@ -118,7 +126,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess private volatile Object beanClass; - private String scope; + private String scope = SCOPE_DEFAULT; private boolean singleton = true; @@ -273,16 +281,16 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * */ public void overrideFrom(BeanDefinition other) { - if (other.getBeanClassName() != null) { + if (StringUtils.hasLength(other.getBeanClassName())) { setBeanClassName(other.getBeanClassName()); } - if (other.getFactoryBeanName() != null) { + if (StringUtils.hasLength(other.getFactoryBeanName())) { setFactoryBeanName(other.getFactoryBeanName()); } - if (other.getFactoryMethodName() != null) { + if (StringUtils.hasLength(other.getFactoryMethodName())) { setFactoryMethodName(other.getFactoryMethodName()); } - if (other.getScope() != null) { + if (StringUtils.hasLength(other.getScope())) { setScope(other.getScope()); } setAbstract(other.isAbstract()); @@ -306,11 +314,11 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess setDependsOn(otherAbd.getDependsOn()); setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed()); setLenientConstructorResolution(otherAbd.isLenientConstructorResolution()); - if (otherAbd.getInitMethodName() != null) { + if (StringUtils.hasLength(otherAbd.getInitMethodName())) { setInitMethodName(otherAbd.getInitMethodName()); setEnforceInitMethod(otherAbd.isEnforceInitMethod()); } - if (otherAbd.getDestroyMethodName() != null) { + if (StringUtils.hasLength(otherAbd.getDestroyMethodName())) { setDestroyMethodName(otherAbd.getDestroyMethodName()); setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod()); } @@ -405,14 +413,17 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess /** * Set the name of the target scope for the bean. - *

Default is "singleton"; the out-of-the-box alternative is "prototype". - * Extended bean factories might support further scopes. + *

Default is singleton status, although this is only applied once + * a bean definition becomes active in the containing factory. A bean + * definition may eventually inherit its scope from a parent bean definitionFor this + * reason, the default scope name is empty (empty String), with + * singleton status being assumed until a resolved scope will be set. * @see #SCOPE_SINGLETON * @see #SCOPE_PROTOTYPE */ public void setScope(String scope) { this.scope = scope; - this.singleton = SCOPE_SINGLETON.equals(scope); + this.singleton = SCOPE_SINGLETON.equals(scope) || SCOPE_DEFAULT.equals(scope); this.prototype = SCOPE_PROTOTYPE.equals(scope); } diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java index 20d8b48f1f..08fbe2537e 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java @@ -1115,7 +1115,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } // Set default singleton scope, if not configured before. - if (mbd.getScope() == null) { + if (!StringUtils.hasLength(mbd.getScope())) { mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON); } diff --git a/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-beans-3.0.xsd b/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-beans-3.0.xsd index 13b8691024..ee24bd1b3f 100644 --- a/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-beans-3.0.xsd +++ b/org.springframework.beans/src/main/resources/org/springframework/beans/factory/xml/spring-beans-3.0.xsd @@ -260,15 +260,14 @@ The scope of this bean: typically "singleton" (one shared instance, which will be returned by all calls to getBean with the given id), or "prototype" (independent instance resulting from each call to getBean). - Default is "singleton". + + By default, a bean will be a singleton, unless the bean has a parent + bean definition in which case it will inherit the parent's scope. Singletons are most commonly used, and are ideal for multi-threaded service objects. Further scopes, such as "request" or "session", might be supported by extended bean factories (e.g. in a web environment). - Note: This attribute will not be inherited by child bean definitions. - Hence, it needs to be specified per concrete bean definition. - Inner bean definitions inherit the singleton status of their containing bean definition, unless explicitly specified: The inner bean will be a singleton if the containing bean is a singleton, and a prototype if -- GitLab