提交 998da2f4 编写于 作者: J Juergen Hoeller

Document destruction callback behavior for inner beans in case of scope mismatch

This commit undoes the previous refinement and rather documents the original behavior.

Issue: SPR-13739
上级 8ed2c470
......@@ -1251,14 +1251,15 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(BeanDefinition.SCOPE_SINGLETON);
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// Check for a mismatch between an inner bean's scope and its containing
// bean's scope: For example, a bean contained in a non-singleton bean
// cannot be a singleton itself. Let's correct this on the fly here.
if (containingBd != null && !mbd.isPrototype() && !mbd.getScope().equals(containingBd.getScope())) {
mbd.setScope(containingBd.isSingleton() ? BeanDefinition.SCOPE_PROTOTYPE : containingBd.getScope());
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Only cache the merged bean definition if we're already about to create an
......
......@@ -31,8 +31,8 @@
(or an ancestor factory).
As alternative to bean references, "inner bean definitions" can be used.
Singleton flags of such inner bean definitions are effectively ignored:
inner beans are typically anonymous prototypes.
Such inner beans do not have an independent lifecycle; they are typically
anonymous nested objects that share the scope of their containing bean.
There is also support for lists, sets, maps, and java.util.Properties
as bean property types or constructor argument types.
......@@ -113,16 +113,19 @@
<xsd:annotation>
<xsd:documentation><![CDATA[
The default 'lazy-init' value; see the documentation for the
'lazy-init' attribute of the 'bean' element.
'lazy-init' attribute of the 'bean' element. The default is "default",
indicating inheritance from outer 'beans' sections in case of nesting,
otherwise falling back to "false".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="default-merge" default="default" type="defaultable-boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
The default 'merge' value; see the documentation for the
'merge' attribute of the various collection elements. The default
is 'false'.
The default 'merge' value; see the documentation for the 'merge'
attribute of the various collection elements. The default is "default",
indicating inheritance from outer 'beans' sections in case of nesting,
otherwise falling back to "false".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
......@@ -130,7 +133,9 @@
<xsd:annotation>
<xsd:documentation><![CDATA[
The default 'autowire' value; see the documentation for the
'autowire' attribute of the 'bean' element. The default is 'default'.
'autowire' attribute of the 'bean' element. The default is "default",
indicating inheritance from outer 'beans' sections in case of nesting,
otherwise falling back to "no" (i.e. no externally driven autowiring).
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
......@@ -305,10 +310,10 @@
service objects. Further scopes, such as "request" or "session", might
be supported by extended bean factories (e.g. in a web environment).
Inner bean definitions inherit the singleton status of their containing
bean definition, unless explicitly specified: The inner bean will be a
Inner bean definitions inherit the scope 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
the containing bean has any other scope.
the containing bean is a prototype, etc.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
......@@ -328,13 +333,15 @@
<xsd:attribute name="lazy-init" default="default" type="defaultable-boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates whether or not this bean is to be lazily initialized.
If false, it will be instantiated on startup by bean factories
that perform eager initialization of singletons. The default is
"false".
Indicates whether this bean is to be lazily initialized. If "false",
it will be instantiated on startup by bean factories that perform eager
initialization of singletons. The effective default is "false".
Note: This attribute will not be inherited by child bean definitions.
Hence, it needs to be specified per concrete bean definition.
Hence, it needs to be specified per concrete bean definition. It can be
shared through the 'default-lazy-init' attribute at the 'beans' level
and potentially inherited from outer 'beans' defaults in case of nested
'beans' sections (e.g. with different profiles).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
......@@ -344,7 +351,7 @@
Controls whether bean properties are "autowired".
This is an automagical process in which bean references don't need
to be coded explicitly in the XML bean definition file, but rather the
Spring container works out dependencies.
Spring container works out dependencies. The effective default is "no".
There are 4 modes:
......@@ -379,7 +386,10 @@
elements, always override autowiring.
Note: This attribute will not be inherited by child bean definitions.
Hence, it needs to be specified per concrete bean definition.
Hence, it needs to be specified per concrete bean definition. It can be
shared through the 'default-autowire' attribute at the 'beans' level
and potentially inherited from outer 'beans' defaults in case of nested
'beans' sections (e.g. with different profiles).
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
......
......@@ -31,8 +31,8 @@
(or an ancestor factory).
As alternative to bean references, "inner bean definitions" can be used.
Singleton flags of such inner bean definitions are effectively ignored:
inner beans are typically anonymous prototypes.
Such inner beans do not have an independent lifecycle; they are typically
anonymous nested objects that share the scope of their containing bean.
There is also support for lists, sets, maps, and java.util.Properties
as bean property types or constructor argument types.
......@@ -310,10 +310,10 @@
service objects. Further scopes, such as "request" or "session", might
be supported by extended bean factories (e.g. in a web environment).
Inner bean definitions inherit the singleton status of their containing
bean definition, unless explicitly specified: The inner bean will be a
Inner bean definitions inherit the scope 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
the containing bean has any other scope.
the containing bean is a prototype, etc.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
......
......@@ -2548,39 +2548,6 @@ public class DefaultListableBeanFactoryTests {
assertEquals("Destroy methods invoked", 1, BeanWithDestroyMethod.closeCount);
}
@Test
public void testDestroyMethodOnInnerBeanAsCustomScope() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
RootBeanDefinition innerBd = new RootBeanDefinition(BeanWithDestroyMethod.class);
innerBd.setScope("custom");
innerBd.setDestroyMethodName("close");
RootBeanDefinition bd = new RootBeanDefinition(BeanWithDestroyMethod.class);
bd.setDestroyMethodName("close");
bd.getPropertyValues().add("inner", innerBd);
lbf.registerBeanDefinition("test", bd);
BeanWithDestroyMethod.closeCount = 0;
lbf.preInstantiateSingletons();
lbf.destroySingletons();
assertEquals("Destroy methods not invoked", 1, BeanWithDestroyMethod.closeCount);
}
@Test
public void testDestroyMethodOnInnerBeanAsCustomScopeWithinPrototype() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
RootBeanDefinition innerBd = new RootBeanDefinition(BeanWithDestroyMethod.class);
innerBd.setScope("custom");
innerBd.setDestroyMethodName("close");
RootBeanDefinition bd = new RootBeanDefinition(BeanWithDestroyMethod.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
bd.setDestroyMethodName("close");
bd.getPropertyValues().add("inner", innerBd);
lbf.registerBeanDefinition("test", bd);
BeanWithDestroyMethod.closeCount = 0;
Object prototypeInstance = lbf.getBean("test");
lbf.destroyBean("test", prototypeInstance);
assertEquals("Destroy methods not invoked", 1, BeanWithDestroyMethod.closeCount);
}
@Test
public void testFindTypeOfSingletonFactoryMethodOnBeanInstance() {
findTypeOfPrototypeFactoryMethodOnBeanInstance(true);
......
......@@ -1397,10 +1397,17 @@ so-called __inner bean__.
</bean>
----
An inner bean definition does not require a defined id or name; the container ignores
these values. It also ignores the `scope` flag. Inner beans are __always__ anonymous and
they are __always__ created with the outer bean. It is __not__ possible to inject inner
beans into collaborating beans other than into the enclosing bean.
An inner bean definition does not require a defined id or name; if specified, the container
does not use such a value as an identifier. The container also ignores the `scope` flag on
creation: Inner beans are __always__ anonymous and they are __always__ created with the outer
bean. It is __not__ possible to inject inner beans into collaborating beans other than into
the enclosing bean or to access them independently.
As a corner case, it is possible to receive destruction callbacks from a custom scope, e.g.
for a request-scoped inner bean contained within a singleton bean: The creation of the inner
bean instance will be tied to its containing bean, but destruction callbacks allow it to
participate in the request scope's lifecycle. This is not a common scenario; inner beans
typically simply share their containing bean's scope.
[[beans-collection-elements]]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册