Closed spring-projects-issues closed 10 years ago
Mihai Postelnicu commented
I think this also happens in version 3.2.5. I have a MethodInvokingFactoryBean with lazy-init=true and no references, that gets eagerly initialized with instantiation. I too have other beans with @Autowired
.
<bean id="startDerby" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="true" autowire-candidate="false">
<property name="targetObject" ref="derbyServer" />
<property name="targetMethod" value="start" />
<property name="arguments" ref="printWriter" />
</bean>
Juergen Hoeller commented
I suppose your reference to the failure because of some internal state was referring to the target method that you're calling, not to MethodInvokingFactoryBean itself? As far as I can tell, the key problem here is that MethodInvokingFactoryBean isn't able to determine the target object type before it actually called the target method...
Juergen
Juergen Hoeller commented
Note that, generally, a direct reference via the bean factory method mechanism won't suffer from this problem since it allows for early introspection of the target method, a la:
<bean id="startDerby" factory-bean="derbyServer" factory-method="start" lazy-init="true" autowire-candidate="false">
<constructor-arg ref="printWriter"/>
</bean>
The only problem in our concrete case here is that Derby's "start" method is declared as void, which makes it getting rejected by Spring's factory method resolution algorithm :-(
Of course, what you can always do is to create a little DerbyStarter class of your own, accepting the Derby NetworkServerControl and a PrintWriter as constructor arguments, and calling that start method programmatically there. Since this is a regular Java class, there won't be any type determination problems and no side effects with by-type autowiring...
Juergen
Juergen Hoeller commented
As a more immediate alternative to MethodInvokingFactoryBean (which more or less expects a result from the call to be exposed to the container), we could offer a MethodInvokingBean that just does the method call, with no further expectations. That would be a regular Java class as well, so no type determination effects to consider... And from the perspective of your bean definition code, all you'd have to do is to change the "MethodInvokingFactoryBean" class name to "MethodInvokingBean"... Would that help?
Juergen
Juergen Hoeller commented
Since it also serves as a straightforward base class for MethodInvokingFactoryBean, I went ahead and extracted a MethodInvokingBean along those lines. To be available in the next 4.0.3 snapshot. Can also easily be copied and used with older Spring versions.
Juergen
Mihai Postelnicu commented
Thanks a lot for explaining what was going on and for the fix!
I think i will upgrade to 4.x anyway, so will give this one a try soon.
Mihai
Benoit Lacelle opened SPR-11196 and commented
If a bean holds an
@Autowire
field, the whole application context seems to be initialized early to check for the type of all beans.I would expect this eager initialisation phase not to actually instantiate the beans, in order to rely on the default bean ordering.
This seems not to be the case when considering some FactoryBean, at least MethodInvokingFactoryBean.
In my case, the MethodInvokingFactoryBean has been loaded right before the
@Autowire
field initialisation (when it is suppose to happen much later).it ssems to be done so as, since this been is not configured yet: MethodInvokingFactoryBean
Then, it instanciates the underlying singleton bean (i.e. it executes the method):
I would expect AbstractBeanFactory.doGetBean to check for typeCheckOnly when calling
like in:
and in this case, it would not execute the method.
In my case, it lead to a hard to spot issue: as the method execution failed, the autowiring logic simply rejected this bean as a candidate. Later, the methodInvokingFactoryBean is executed again, but it failed for an obscure reason as the first (failed) call has changed some internal state.
Here is a stack leasing to the first method call:
Affects: 3.1.3
Referenced from: commits https://github.com/spring-projects/spring-framework/commit/cf290ab42a22e412eb55db34c5b43aadcb356d3f
1 votes, 4 watchers