Ich habe einige seltsame Probleme, wo FactoryBean.getObject()
aufgerufen wird, bevor die FactoryBean
initialisiert wird. Ich habe ein kleines Sample erstellt, das etwas Mist aufweist. Es ist nicht das genaue Problem, das ich mit meiner größeren Anwendung sehe, aber ich denke, es ist verwandt.Spring Anwendungskontext - FactoryBean.getObject() aufgerufen vor FactoryBean initialisiert
Dies wird durch eine kreisförmige Referenz wahrscheinlich verursacht, wo
node1
Referenzennode2
- und
node2
Referenzennode1
I Frühling bin mit Version 4.2.4.RELEASE
SpringTestContext.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
>
<bean id="node1" class="com.hsbc.gbm.dsl.dtm.test.SpringTest$NodeFactory">
<property name="next" ref="node2" />
</bean>
<bean id="node2" class="com.hsbc.gbm.dsl.dtm.test.SpringTest$NodeFactory">
<property name="prev" ref="node1" />
</bean>
</beans>
SpringTest.java
public class SpringTest {
public static class Node {
private final Node next;
private final Node prev;
public Node(Node prev, Node next) {
super();
this.prev = prev;
this.next = next;
}
}
public static class NodeFactory implements FactoryBean<Node>, BeanNameAware, ApplicationContextAware, InitializingBean {
private Node next;
private Node prev;
private String beanName;
private Node node;
private ApplicationContext applicationContext;
private boolean initialized;
public void setNext(Node next) {
this.next = next;
}
public void setPrev(Node prev) {
this.prev = prev;
}
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Class<?> getObjectType() {
return Node.class;
}
@Override
public void afterPropertiesSet() throws Exception {
node = new Node(prev, next);
initialized = true;
}
@Override
public Node getObject() {
System.out.println(String.format("NodeFactory: getObject() beanName=%s, initialized=%s, applicationContext=%s",
beanName, initialized, applicationContext));
if (!initialized) {
throw new RuntimeException("NodeFactory not initialized before getObject() for " + beanName);
}
return node;
}
public boolean isSingleton() {
return true;
}
}
@Test
public void test() {
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext("com/hsbc/gbm/dsl/dtm/test/SpringTestContext.xml");
appContext.start();
}
}
Ausgabe
NodeFactory: getObject() beanName=null, initialized=false, applicationContext=null
Exception
Caused by: java.lang.RuntimeException: NodeFactory not initialized before getObject() for null
at com.foo.SpringTest$NodeFactory.getObject(SpringTest.java:74)
at com.foo.SpringTest$NodeFactory.getObject(SpringTest.java:1)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168)
... 53 more
Voll Trace
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'node1' defined in class path resource [com/foo/SpringTestContext.xml]: Cannot resolve reference to bean 'node2' while setting bean property 'next'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'node2' defined in class path resource [com/foo/SpringTestContext.xml]: Cannot resolve reference to bean 'node1' while setting bean property 'prev'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'node1': FactoryBean threw exception on object creation; nested exception is java.lang.RuntimeException: NodeFactory not initialized before getObject() for null
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:753)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.foo.SpringTest.test(SpringTest.java:117)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'node2' defined in class path resource [com/foo/SpringTestContext.xml]: Cannot resolve reference to bean 'node1' while setting bean property 'prev'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'node1': FactoryBean threw exception on object creation; nested exception is java.lang.RuntimeException: NodeFactory not initialized before getObject() for null
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 38 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'node1': FactoryBean threw exception on object creation; nested exception is java.lang.RuntimeException: NodeFactory not initialized before getObject() for null
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:175)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:127)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1585)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:254)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 48 more
Caused by: java.lang.RuntimeException: NodeFactory not initialized before getObject() for null
at com.foo.SpringTest$NodeFactory.getObject(SpringTest.java:74)
at com.foo.SpringTest$NodeFactory.getObject(SpringTest.java:1)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168)
... 53 more