-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
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
/**
* Return the type of object that this FactoryBean creates,
* or <code>null</code> if not known in advance.
*/
public Class<?> getObjectType() {
if (!isPrepared()) {
// Not fully initialized yet -> return null to indicate "not known yet".
return null;
}
return getPreparedMethod().getReturnType();
}
Then, it instanciates the underlying singleton bean (i.e. it executes the method):
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 225
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 291
DefaultListableBeanFactory(AbstractBeanFactory).getTypeForFactoryBean(String, RootBeanDefinition) line: 710
I would expect AbstractBeanFactory.doGetBean to check for typeCheckOnly when calling
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
like in:
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
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:
MyProjectClass(MyProjectClass).myProjectMethod(String) line: myProjectLine
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
MethodInvokingFactoryBean(MethodInvoker).invoke() line: 273
MethodInvokingFactoryBean.doInvoke() line: 162
MethodInvokingFactoryBean.afterPropertiesSet() line: 152
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).invokeInitMethods(String, Object, RootBeanDefinition) line: 1514
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).initializeBean(String, Object, RootBeanDefinition) line: 1452
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 519
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 456
AbstractBeanFactory$1.getObject() line: 294
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 225
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 291
DefaultListableBeanFactory(AbstractBeanFactory).getTypeForFactoryBean(String, RootBeanDefinition) line: 1356
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).getTypeForFactoryBean(String, RootBeanDefinition) line: 710
DefaultListableBeanFactory(AbstractBeanFactory).isTypeMatch(String, Class<?>) line: 519
DefaultListableBeanFactory.doGetBeanNamesForType(Class<?>, boolean, boolean) line: 339
DefaultListableBeanFactory.getBeanNamesForType(Class<?>, boolean, boolean) line: 316
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean) line: 187
DefaultListableBeanFactory.findAutowireCandidates(String, Class<?>, DependencyDescriptor) line: 857
DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, Class<?>, String, Set<String>, TypeConverter) line: 814
DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set<String>, TypeConverter) line: 731
AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(Object, String, PropertyValues) line: 485
InjectionMetadata.inject(Object, String, PropertyValues) line: 92
AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String) line: 284
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean(String, AbstractBeanDefinition, BeanWrapper) line: 1106
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 517
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 456
AbstractBeanFactory$1.getObject() line: 294
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 225
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 291
DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 193
BeanDefinitionValueResolver.resolveReference(Object, RuntimeBeanReference) line: 323
BeanDefinitionValueResolver.resolveValueIfNecessary(Object, Object) line: 107
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).applyPropertyValues(String, BeanDefinition, BeanWrapper, PropertyValues) line: 1360
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean(String, AbstractBeanDefinition, BeanWrapper) line: 1118
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 517
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 456
AbstractBeanFactory$1.getObject() line: 294
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 225
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 291
DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 193
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 284
DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 193
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 284
DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 193
DefaultListableBeanFactory.preInstantiateSingletons() line: 587
XmlWebApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 925
XmlWebApplicationContext(AbstractApplicationContext).refresh() line: 472
ContextLoaderListener(ContextLoader).configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext, ServletContext) line: 383
ContextLoaderListener(ContextLoader).initWebApplicationContext(ServletContext) line: 283
ContextLoaderListener.contextInitialized(ServletContextEvent) line: 111
WebAppContext(ContextHandler).callContextInitialized(ServletContextListener, ServletContextEvent) line: 771
WebAppContext(ServletContextHandler).callContextInitialized(ServletContextListener, ServletContextEvent) line: 424
WebAppContext(ContextHandler).startContext() line: 763
WebAppContext(ServletContextHandler).startContext() line: 249
WebAppContext.startContext() line: 1250
WebAppContext(ContextHandler).doStart() line: 706
WebAppContext.doStart() line: 492
WebAppContext(AbstractLifeCycle).start() line: 64
Server(HandlerWrapper).doStart() line: 95
Server.doStart() line: 277
Server(AbstractLifeCycle).start() line: 64
MreJettyServer.start(int) line: 85
MreJettyServer.main(String[]) line: 59
Affects: 3.1.3
Referenced from: commits cf290ab
1 votes, 4 watchers