Revised naming for prototype inner beans to avoid excessive unique name calculation
Restored original singleton-only adaptInnerBeanName behavior, avoiding endless unique name calculation for every single prototype instance. Non-named inner BeanDefinition objects now suffixed with an identity hex code analogous to non-named XML bean definitions, largely avoiding naming collisions to begin with. After SPR-11246, post-processors can deal with unstable classes per bean name, so occasional collisions aren't a hard problem anymore. Issue: SPR-11545
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -81,6 +81,7 @@ class BeanDefinitionValueResolver {
|
|||||||
this.typeConverter = typeConverter;
|
this.typeConverter = typeConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a PropertyValue, return a value, resolving any references to other
|
* Given a PropertyValue, return a value, resolving any references to other
|
||||||
* beans in the factory if necessary. The value could be:
|
* beans in the factory if necessary. The value could be:
|
||||||
@@ -123,7 +124,9 @@ class BeanDefinitionValueResolver {
|
|||||||
else if (value instanceof BeanDefinition) {
|
else if (value instanceof BeanDefinition) {
|
||||||
// Resolve plain BeanDefinition, without contained name: use dummy name.
|
// Resolve plain BeanDefinition, without contained name: use dummy name.
|
||||||
BeanDefinition bd = (BeanDefinition) value;
|
BeanDefinition bd = (BeanDefinition) value;
|
||||||
return resolveInnerBean(argName, "(inner bean)", bd);
|
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
|
||||||
|
ObjectUtils.getIdentityHexString(bd);
|
||||||
|
return resolveInnerBean(argName, innerBeanName, bd);
|
||||||
}
|
}
|
||||||
else if (value instanceof ManagedArray) {
|
else if (value instanceof ManagedArray) {
|
||||||
// May need to resolve contained runtime references.
|
// May need to resolve contained runtime references.
|
||||||
@@ -256,20 +259,25 @@ class BeanDefinitionValueResolver {
|
|||||||
mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition);
|
mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition);
|
||||||
// Check given bean name whether it is unique. If not already unique,
|
// Check given bean name whether it is unique. If not already unique,
|
||||||
// add counter - increasing the counter until the name is unique.
|
// add counter - increasing the counter until the name is unique.
|
||||||
String actualInnerBeanName = adaptInnerBeanName(innerBeanName);
|
String actualInnerBeanName = innerBeanName;
|
||||||
|
if (mbd.isSingleton()) {
|
||||||
|
actualInnerBeanName = adaptInnerBeanName(innerBeanName);
|
||||||
|
}
|
||||||
this.beanFactory.registerContainedBean(actualInnerBeanName, this.beanName);
|
this.beanFactory.registerContainedBean(actualInnerBeanName, this.beanName);
|
||||||
// Guarantee initialization of beans that the inner bean depends on.
|
// Guarantee initialization of beans that the inner bean depends on.
|
||||||
String[] dependsOn = mbd.getDependsOn();
|
String[] dependsOn = mbd.getDependsOn();
|
||||||
if (dependsOn != null) {
|
if (dependsOn != null) {
|
||||||
for (String dependsOnBean : dependsOn) {
|
for (String dependsOnBean : dependsOn) {
|
||||||
this.beanFactory.getBean(dependsOnBean);
|
|
||||||
this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
|
this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
|
||||||
|
this.beanFactory.getBean(dependsOnBean);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Actually create the inner bean instance now...
|
||||||
Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null);
|
Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null);
|
||||||
if (innerBean instanceof FactoryBean) {
|
if (innerBean instanceof FactoryBean) {
|
||||||
boolean synthetic = mbd.isSynthetic();
|
boolean synthetic = mbd.isSynthetic();
|
||||||
return this.beanFactory.getObjectFromFactoryBean((FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
|
return this.beanFactory.getObjectFromFactoryBean(
|
||||||
|
(FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return innerBean;
|
return innerBean;
|
||||||
|
|||||||
@@ -129,6 +129,15 @@
|
|||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="hasInnerBeansAsPrototype" class="org.springframework.tests.sample.beans.TestBean" scope="prototype">
|
||||||
|
<constructor-arg>
|
||||||
|
<bean id="innerBean" class="org.springframework.tests.sample.beans.TestBean" destroy-method="destroy">
|
||||||
|
<constructor-arg><value>inner1</value></constructor-arg>
|
||||||
|
<constructor-arg type="int"><value>6</value></constructor-arg>
|
||||||
|
</bean>
|
||||||
|
</constructor-arg>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="hasInnerBeansWithoutDestroy" class="org.springframework.tests.sample.beans.TestBean">
|
<bean id="hasInnerBeansWithoutDestroy" class="org.springframework.tests.sample.beans.TestBean">
|
||||||
<constructor-arg><value>hasInner</value></constructor-arg>
|
<constructor-arg><value>hasInner</value></constructor-arg>
|
||||||
<constructor-arg index="1" type="int"><value>5</value></constructor-arg>
|
<constructor-arg index="1" type="int"><value>5</value></constructor-arg>
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import java.net.URL;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import org.springframework.aop.framework.ProxyFactory;
|
import org.springframework.aop.framework.ProxyFactory;
|
||||||
import org.springframework.aop.support.AopUtils;
|
import org.springframework.aop.support.AopUtils;
|
||||||
@@ -65,7 +65,6 @@ import org.springframework.util.ClassUtils;
|
|||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.springframework.util.SerializationTestUtils;
|
import org.springframework.util.SerializationTestUtils;
|
||||||
import org.springframework.util.StopWatch;
|
import org.springframework.util.StopWatch;
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
@@ -229,6 +228,20 @@ public final class XmlBeanFactoryTests {
|
|||||||
assertEquals("inner1", innerForConstructor.getName());
|
assertEquals("inner1", innerForConstructor.getName());
|
||||||
assertEquals(6, innerForConstructor.getAge());
|
assertEquals(6, innerForConstructor.getAge());
|
||||||
|
|
||||||
|
hasInnerBeansForConstructor = (TestBean) xbf.getBean("hasInnerBeansAsPrototype");
|
||||||
|
innerForConstructor = (TestBean) hasInnerBeansForConstructor.getSpouse();
|
||||||
|
assertNotNull(innerForConstructor);
|
||||||
|
assertEquals("innerBean", innerForConstructor.getBeanName());
|
||||||
|
assertEquals("inner1", innerForConstructor.getName());
|
||||||
|
assertEquals(6, innerForConstructor.getAge());
|
||||||
|
|
||||||
|
hasInnerBeansForConstructor = (TestBean) xbf.getBean("hasInnerBeansAsPrototype");
|
||||||
|
innerForConstructor = (TestBean) hasInnerBeansForConstructor.getSpouse();
|
||||||
|
assertNotNull(innerForConstructor);
|
||||||
|
assertEquals("innerBean", innerForConstructor.getBeanName());
|
||||||
|
assertEquals("inner1", innerForConstructor.getName());
|
||||||
|
assertEquals(6, innerForConstructor.getAge());
|
||||||
|
|
||||||
xbf.destroySingletons();
|
xbf.destroySingletons();
|
||||||
assertTrue(inner1.wasDestroyed());
|
assertTrue(inner1.wasDestroyed());
|
||||||
assertTrue(inner2.wasDestroyed());
|
assertTrue(inner2.wasDestroyed());
|
||||||
|
|||||||
Reference in New Issue
Block a user