Description
Simon Raess opened SPR-1487 and commented
Spring ApplicationContext throws an exception, claiming a circular dependency, in a very simple scenario:
- two classes, One and Two
- One has a single constructor argument of type Two
- Two has a single property of type One
The following context XML works:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="two" class="Two">
<property name="one"><ref local="one"/></property>
</bean>
<bean id="one" class="One">
<constructor-arg><ref local="two"/></constructor-arg>
</bean>
</beans>
Just reversing the bean definitions results in a total different situation:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="one" class="One">
<constructor-arg><ref local="two"/></constructor-arg>
</bean>
<bean id="two" class="Two">
<property name="one"><ref local="one"/></property>
</bean>
</beans>
The following exception is thrown:
Nov 21, 2005 1:37:15 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in factory [org.springframework.beans.factory.support.DefaultListableBeanFactory defining beans [one,two]; root of BeanFactory hierarchy]
Nov 21, 2005 1:37:15 PM org.springframework.beans.factory.support.AbstractBeanFactory destroySingletons
INFO: Destroying singletons in factory {org.springframework.beans.factory.support.DefaultListableBeanFactory defining beans [one,two]; root of BeanFactory hierarchy}
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'one' defined in class path resource [context.xml]: Can't resolve reference to bean 'two' while setting property 'constructor argument'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'two' defined in class path resource [context.xml]: Can't resolve reference to bean 'one' while setting property 'one'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'one': Requested bean is currently in creation (circular reference when autowiring constructor?)
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'two' defined in class path resource [context.xml]: Can't resolve reference to bean 'one' while setting property 'one'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'one': Requested bean is currently in creation (circular reference when autowiring constructor?)
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'one': Requested bean is currently in creation (circular reference when autowiring constructor?)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:186)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:147)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:176)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:105)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1012)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:823)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:345)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:147)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:176)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:105)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveConstructorArguments(AbstractAutowireCapableBeanFactory.java:713)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:611)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:329)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:147)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:275)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:318)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:81)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:66)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:57)
at Test.main(Test.java:7)
So first of all, the order of bean definitions is in fact significant. Second, Spring fails to construct the object graph in this simple case. Note, I was using the following simple test program:
public class Test {
public static void main(String[] args) {
BeanFactory factory = new ClassPathXmlApplicationContext("context.xml");
Two two = (Two) factory.getBean("two");
System.out.println(two);
System.out.println(two.getOne());
}
}
Using an XmlBeanFactory works, independent of the order of those two bean elements in the XML.
public class Test {
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));
Two two = (Two) factory.getBean("two");
System.out.println(two);
System.out.println(two.getOne());
}
}
Affects: 1.2.5, 1.2.6
0 votes, 5 watchers