Reputation: 1
I tried writing a test program on MethodInvokingFactoryBean
, having 2 beans declared as below.
<bean id="test2" class="test3">
</bean>
<bean id="m2" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="false" depends-on="test4">
<property name="targetObject"><ref local="test2"></ref></property>
<property name="targetMethod"><value>execute</value></property>
<property name="arguments">
<list>
<value>abc</value>
<ref local="test4"></ref>
</list>
</property>
</bean>
<bean id="test4" class="test5"></bean>
<bean id="m3"class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="true">
<property name="targetObject"><ref local="test4"></ref></property>
<property name="targetMethod"><value>execute</value></property>
<property name="arguments">
<list>
<value>xyz</value>
</list>
</property>
</bean>
I am getting the bean via:
test3 obj3 = (test3) _context.getBean("test2");
The usecase for me here is,
before executing the Method execute
in test2, I should be able to execute the Method execute
lying on bean "test4" , as "test4" is one of my arguments for running execute
Method in "test2".
And also, I need everything to be made lazy-init = true
.
I tried with the above, but the Method "execute" in test4 is not getting called before executing Method in test2.
Kindly help me to solve this.
Upvotes: 0
Views: 3782
Reputation: 22514
execute
in test4
is not going to be called as m3 is declared lazy-init="true"
. The chain of dependencies is as follows:
So at startup, Spring initializes test2, test4 and then m2. It does not do m3 as it is lazy. Then, when you request bean test2 to the context, it sees that test4 has already been completely initialized and just returns it.
Now, you are saying that you need everything as lazy-init="true"
, but in fact most of your beans are eager. Would making everything really lazy and changing it in this way fulfill your requirements?
<bean id="test2" class="test3" lazy-init="true" depends-on="m2">
</bean>
<bean id="m2" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="true" depends-on="m3">
<property name="targetObject"><ref local="test2"></ref></property>
<property name="targetMethod"><value>execute</value></property>
<property name="arguments">
<list>
<value>abc</value>
<ref local="test4"></ref>
</list>
</property>
</bean>
<bean id="test4" class="test5" lazy-init="true"></bean>
<bean id="m3"class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="true">
<property name="targetObject"><ref local="test4"></ref></property>
<property name="targetMethod"><value>execute</value></property>
<property name="arguments">
<list>
<value>xyz</value>
</list>
</property>
</bean>
In this way, everything is lazy-init so Spring should not do any initialization by default on startup. Now, the chain of dependencies is:
So when you request bean test2, initialization for m2, m3 and test4 will be triggered. It is not pretty because there is a circular dependency between test2 and m2, but it should work.
Anyway, your setup is quite complicated and if you cannot simplify it, I think you are in the point where Spring starts getting in your way. I recommend you to write a single service in Java that hides the management of those dependencies, so you can remove all those XML and put a single, simple, straightforward bean declaration instead. Something similar to this, where test2Factory hides all the ugliness:
<bean id="test2Factory" class="test2FactoryClass">
<property name="test4"><bean class="test5"/></property>
</bean>
<bean id="test2" factory-bean="test2Factory" factory-method="getInstance"/>
UPDATE
This is getting messy, you could try declaring some artificial bean to break circularity:
<bean id="rawTest2" class="test3" lazy-init="true">
</bean>
<bean id="m2" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="true" depends-on="m3">
<property name="targetObject"><ref local="rawTest2"></ref></property>
<property name="targetMethod"><value>execute</value></property>
<property name="arguments">
<list>
<value>abc</value>
<ref local="test4"></ref>
</list>
</property>
</bean>
<bean id="test2" class="org.springframework.beans.factory.config.PropertyPathFactoryBean" lazy-init="true" depends-on="m2">
<property name="targetBeanName" value="rawTest2"/>
<property name="propertyPath" value=" "/><!-- One space inside quotes -->
</bean>
<!-- m3 and test4 stay the same as before -->
Although at this point I would just code the thing in Java...
Upvotes: 2