2016-11-07 4 views
3

내 applicationContext 초기화가 Spring 3.2.1에서 잘 작동했습니다.Spring 4.0.9 applicationContext 초기화가 멈추지 만 3.2.1이 아닌 이유는 무엇입니까?

그러나 코드 나 bean 정의를 변경하지 않고 4.0.9로 업그레이드했을 때 초기화가 중단되었습니다. 다음 진술은 계속 발생했습니다. 그래도 명확한 순환 참조가 없습니다.

Requested bean is currently in creation: Is there an unresolvable circular reference? 

나는 계속 조사했다. 나는 의도적으로 빈 정의를 제거했다.

  • 봄 3.2.1 예상 결과가 있습니다. 치명적인 오류가 거의 즉시 발생했습니다.
  • 스프링 4.0.9는 여전히이 무한 루프에 들어가서, 다른 씨드 빈 정의를 찾아 내서 작동하도록했습니다.

다음은 계속 발생하는 로그 문입니다.

[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 

변경된 기능은 무엇입니까? 어떤 아이디어라도 도움이 될 것입니다. 봄 3.X에 있지만 4.0.9에서 작동 모두 봄 3.x 및 4.x의

<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> 
    .... 

콩 정의에서 작업


콩 정의. 나는 봄 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> 

오류가

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 빌드 프로 시저를 실행하기 위해 xml에서 @Configuration 클래스로 Bean 위를 이동해야했습니다.

----------------------- UPDATE 나는이 문제를 발견 : 'MethodInvokingFactoryBeans와의 t [MIB] 용도'. 몇 가지 이유 때문에, Spring 4는 많은 수의 MIB가있는 상황에서 혼란스러워졌습니다. 정확히 같은 코드 기반은 Spring 3과 함께 잘 작동했습니다. 다양한 MIB에 의해 수행 된 모든 로직을 ApplicationListener로 마이그레이션했습니다. ApplicationListener는 MIB에 대한 의도 된 대체품이 아니지만 제 경우에는 MIB가 Spring에서 관리하지 않는 클래스에 Spring Bean의 정적 삽입을 수행하기 때문에 리스너에서 논리를 재현 할 수 있습니다. 이 문제를 해결할뿐만 아니라 Spring 시작 시간을 300 초에서 ~ 200 초로 줄였습니다.

불행히도 스프링의 근본 원인을 파악하거나 작은 코드베이스 (여기에 공유)에서 문제를 재현 할 수 없었습니다.

+0

someDataSource라는 bean이 있습니까, 정의가 표시 될 수 있습니까? 종속성이 있습니까?이를 볼 수 있습니까? –

+0

@RC 게시 된 bean 정의. 이것을 봐주세요. – phani

답변

3

제거 XML에서

<bean class="SomeSpringConfiguration" /> 

, 그것은 이미 @Configuration 주석입니다. 스캔중인 경우 콩이 두 번 생성 될 가능성이 있습니다. 모든 것을 Javaconfig로 옮겨야합니다.

+1

응답 해 주셔서 감사합니다. 제안 된 행을 제거했지만 SomeSpringConfiguration 패키지에 대해 자동 스캔이 활성화되지 않았습니다. 그래서'을 추가했습니다. 아직도 운이 없다; 그것은 무한 루프로 진행되고 있습니다. Btw, 내 게시물 하단에 추가 된 새로운 세부 사항을 확인하십시오. – phani

1

순환 참조는 많은 빈을 가지고 있고 함께 모으는 경우 조심하지 않을 때 개발 중에 일반적입니다. stacktrace에는 순환 참조가 시작하고 끝나는 위치를 알려주는 빈의 전체 목록이 있어야합니다.

나는 무작위 순환 참조을 본 적이 없으며 (지난 7 년 동안 순환 참조가 여러 번 발생했습니다)! 내가 아는 한, 종속성 트리를 작성하고 빈을 인스턴스화/연결하는 코드는 결정적입니다. 따라서 항상 실행될 때마다 동일한 순환 참조를 가져야합니다. 그렇게하지 않으면, 내가 할 수있는 당신이 사용하고있는 봄 버전에서 문제가 두 가지 이유

  • 의 유일한 것은 당신이
  • (나는 이것에 대한 단위 테스트가 99 % 확신) Bean 인스턴스화의 일부로 스레드를 시작하는 하나 이상의 Bean 중 하나이며, 스레드는 applicationContext를 사용하여 다른 Bean을 느리게로드합니다 (컨텍스트가로드되는 동안).

스프링 클래스를 가르치는 경우에는 생성자가 필드 할당 만 포함하는 것이 좋습니다. 스레드 (또는 수명주기가있는 다른 모든 요소)를 시작해야하는 경우 라이프 사이클 메소드를 사용해야합니다. 필자는 개인적으로 SmartLifeCycle (InitializingBean/DisposableBean, @ PostConstruct/@ PreDestroy)을 구현하는 것을 선호합니다. 이렇게하면 모든 Bean이 인스턴스화되고 함께 연결될 때까지 아무 것도 시작되지 않기 때문입니다.

+0

응답 해 주셔서 감사합니다. 초기화하는 동안'thread-names'를 확인하겠습니다. 당신은 부분적으로 이것에 대해 언급 했었지만 Spring 초기화는 결정적이며 Spring 3.x에서 성공적이었고 Spring 4.x (4.0에서 4.3) 중 하나에서 결정적이며 실패했습니다. 이는 3.x 및 4.x 비교 중에 코드가 없거나 bean 정의가 변경된 것입니다. – phani

+0

여러 스레드를 찾을 수 없습니다. – phani

+0

여러 개의 Spring 컨텍스트를 사용하거나 일부 빈을 비활성화하여 복잡성을 줄일 수있는 다른 방법을 사용합니다. 추가 스레드가 없다면 어딘가에서 HashMap의 임의성이 발생할 수 있습니다. 아마도 새로운 버전의 Spring을 사용해보십시오. 내 최선의 제안은 예외가 던져지는 곳에서 중단 점을 놓은 다음 중단 될 때 콜 스택을보고 거기에 어떻게 도달했는지 살펴보고 무언가가 돋보일 때까지 봄 레이어를 살펴 보는 것입니다. 기대하는 심각한 디버깅이있는 것 같습니다. –

1

Strelok이 말한 것처럼 핵심은 주석과 xml 구성을 혼합합니다.

@Configuration 어노테이션의 핵심은 xml을 피하는 것이다. XML에서 SomeSpringConfiguration을 제거한 후 패키지에 대한 구성 요소 검사를 추가 할 때.

someDataSource의 배수가 여러 곳 (@Bean 주석 및 xml)에 정의되어 있기 때문에이 배수를 만드는 것이 좋습니다.

주석과 xml을 섞어서 사용하지 말고, 그 중 하나만 사용하고 그대로 사용하십시오.이 문제는 해결되지는 않지만 적어도 발견하기 쉽습니다.

예제 프로젝트를 만들고 어딘가에 업로드 할 수 있다면 여전히이 문제가있는 경우 자세히 살펴볼 수 있습니다.

+0

답변 해 주셔서 감사합니다. 애플리케이션에는'xml, @Component 및 @ Configuration'에 /로 정의 된 수천 개의 bean이 있습니다. 그들 모두는 공존한다. 나는 그들 중 하나만 사용하는 것이 바람직하지만 불행히도이 큰 프로젝트에서 문제가되지 않는다는 것에 동의합니다. 여기에서 가장 중요한 점은 Spring 3.2.x에서는 똑같은 코드가 제대로 작동하지만 Spring 4.x.y에서는 제대로 작동하지 않는다는 것입니다. – phani