我的applicationContext初始化在Spring 3.2.1中运行良好。
但是当我在不更改任何代码或bean定义的情况下升级到4.0.9时,初始化卡住了。以下声明继续发生。但是没有明显的循环引用。
Requested bean is currently in creation: Is there an unresolvable circular reference?
我继续调查。我故意删除了一个bean定义。
这是继续发生的日志声明。
[factory.support.DefaultListableBeanFactory.getTypeForFactoryBean()] - Ignoring bean creation exception on FactoryBean type check:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'someSeedBean-which-is-different-in-every-instance-of-this-log' defined in the class path resource ........ ;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'someDataSource' is defined
改变了什么?任何想法都会有所帮助。
适用于Spring 3.x和4.x
的Bean定义<bean id="abstractDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" abstract="true" scope="singleton">
<property ....>
</bean>
<bean id="someDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" scope="singleton" parent="abstractDataSource">
<property name="driverClass" .... />
</bean>
<bean id="someSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource"> <ref bean="someDataSource" /> </property>
<property name="packagesToScan"> <list>......</list> </property>
....
Bean定义适用于Spring 3.x但不适用于4.0.9。
@Configuration
public class SomeSpringConfiguration{
// Moving this beanDef to Java for features not available in XML
@Bean(destroyMethod = "close")
public DataSource someDataSource() { // also tried setting this to ComboPooledDataSource
// verified that this beanDefinition is recognized by Spring
// but this bean is never created / this method is never executed
...
return datasource;
}
}
<bean class="SomeSpringConfiguration" />
<bean id="someSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource"> <ref bean="someDataSource" /> </property>
<property name="packagesToScan"> <list>......</list> </property>
....
</bean>
我在Spring 4.0.9中遇到的错误是
Cannot resolve reference to bean 'someSessionFactory' while setting constructor argument;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'someSessionFactory':
Requested bean is currently in creation: Is there an unresolvable circular reference?
请注意,该应用程序在/ xml,@ Component和@Configuration中定义了数千个bean。我不得不将bean从xml移到@Configuration类以执行复杂的bean构建过程。
----------------------- UPDATE
我发现了问题:&#39;吨MethodInvokingFactoryBean [MIB]用法&#39;。出于某种原因,Spring 4在存在大量MIB时感到困惑。完全相同的代码库在Spring 3中运行良好。我将各种MIB执行的所有逻辑迁移到ApplicationListener。请注意,ApplicationListener不是MIB的预期替代品,但在我的情况下,我可以在监听器中重现逻辑,因为MIB只是将Spring bean静态注入到不由Spring管理的类中。它不仅解决了这个问题,而且将Spring启动时间从~300秒减少到约200秒。
不幸的是,我既不能在Spring中找出根本原因,也不能在较小的代码库中重现这个问题(在这里分享)。
答案 0 :(得分:3)
删除
<bean class="SomeSpringConfiguration" />
来自XML,它已经使用@Configuration
进行了注释。如果它被扫描,它可能会被创建两次。你应该把所有东西都搬到Javaconfig。
答案 1 :(得分:1)
循环引用在开发过程中很常见,当你有很多bean并且在将它们一起自动装配时不小心。堆栈跟踪应包含完整的bean列表,告诉您循环引用的开始和结束位置。
我从未见过随机循环引用(我在过去7年中多次遇到循环引用)!据我所知,构建依赖树并实例化/连接bean的代码是确定性的。因此,每次运行时都应该始终获得相同的循环引用。如果你不这样做,我只能有两个原因
当我教Spring类时,我建议构造函数应该只包含字段赋值,如果需要启动线程(或生命周期中的任何其他内容),则应使用生命周期方法。我个人更喜欢实现SmartLifeCycle(通过InitializingBean / DisposableBean,@ PostConstruct / @ PreDestroy),因为这样可以确保在所有bean实例化并连接在一起之后不会启动任何内容。
答案 2 :(得分:1)
它的核心是Strelok所说的,你正在混合注释和xml配置。
@Configuration注释的要点是避免使用xml。从xml中删除SomeSpringConfiguration后添加组件扫描时。
您将开始创建someDataSource的倍数,因为它在多个位置定义(@Bean注释和xml)。
请避免混合注释和xml,只使用其中一个并坚持下去,如果不解决这个问题,至少会更容易发现。
如果你可以创建一个示例项目并将其上传到某个地方,我可以仔细查看你是否还有这个问题。