Reputation: 2234
I have following class which I am trying to instantiate through spring.
class MyBean{
MyBean myBeanFallback;
MyDataObject myDataObject;
public void setMyBeanFallback(MyBean myBeanFallback){
this.myBeanFallback = myBeanFallback;
}
MyBean(MyDataObject myDataObject){
this.myDataObject = myDataObject;
}
}
Following is the spring config I am tryin got use to load this :
<bean name="myNewBean" class="MyBean"
scope="prototype">
<constructor-arg index="0" type="MyDataObject" >
<null />
</constructor-arg>
<property name="myBeanFallback" ref="myOldBean" />
</bean>
<bean name="myOldBean" class="MyBean"
scope="prototype">
<constructor-arg index="0" type="MyDataObject" >
<null />
</constructor-arg>
</bean>
In my application code, I may instantiate the myOldBean which has data and no fallback. else I may instantiate the myNewBean which has data and also has myOldBean as fallback, which in turn also needs to have same myDataObject
getNewBean(MyData mydata){
return (MyBean) context.getBean("myNewBean", new Object[] { mydata });
}
getOldBean(MyData mydata){
return (MyBean) context.getBean("myOldBean", new Object[] { mydata });
}
The problem I am facing now is that while getting myNewBean, the fallback getNewBean doesn't get populated with mydata, rather takes null.
Any pointers on how this can be fixed ?
Upvotes: 0
Views: 6406
Reputation: 11377
@bellabax has the right idea.
The other point on this is that you can use a FactoryBean (link to Spring manual) to customize the construction of a bean that is scope=prototype. So you can leave myOldBean as it is and then customize the construction of myNewBean by doing something like this:
<bean name="myNewBean" class="MyNewFactoryBean" scope="prototype">
<property name="myData"><!-- however you want to provide the value for this --></property>
</bean>
And then the FactoryBean implementation:
public class MyNewFactoryBean implements FactoryBean<MyBean> {
protected MyData myData;
public void setMyData(MyData d) {
myData = d;
}
@Override
public MyBean getObject() throws Exception {
MyBean myBean = new MyBean();
myBean.setMyBeanFallback(context.getBean("myOldBean", new Object[] { myData }));
return myBean;
}
@Override
public Class<MyBean> getObjectType() {
return MyBean.class;
}
....
}
When you do it like that, you can (later in your code) do something like context.getBean("myNewBean")
just as you normally would and it will invoke your custom instantiation logic from MyNewFactoryBean.
Upvotes: 0
Reputation: 18383
You can't do that with Spring; when you get myNewBean
, myBeanFallback
(myOldBean
) property is correctly instatiated with null
value as specified in constructor and you can't change this behaviour because myBeanFallback
is not constructed using FactoryBean.getBean()
but autowired.
Maybe using a factory in this way can be a solution:
class MyBeanFactory {
public getNewBean(MyData mydata){
MyBean myBean = (MyBean) context.getBean("myNewBean", new Object[] { mydata });
MyBean myBeanFallback = getOldBean(myData);
myBean.setMyBeanFallback(myBeanFallback);
return myBean;
}
public getOldBean(MyData mydata){
return (MyBean) context.getBean("myOldBean", new Object[] { mydata });
}
}
and beans.xml
<bean name="myNewBean" class="MyBean" scope="prototype" />
<bean name="myOldBean" class="MyBean" scope="prototype" />
Upvotes: 1
Reputation: 1616
Never done this kind of things but here are my $.05: because your myOldBean definition is scoped as prototype, internally in Spring it is known with that name but it is null. Hence when you create a myNewBean instance it will use that null reference.
I don't think that Spring was intended to be used that way. I might be wrong but the whole constructor passing values to getBean is bypass one of the goals of Spring: let spring configure and link your objects like you specify in the xml file, mixing the xml with creating beans in code will result in a mess like your case...
So my advice would be: try to put the whole configuration in spring.
Upvotes: 0