Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Spring.... BeanCurrentlyInCreationException


Автор: anti_snayper 29.4.2010, 11:22
Добрый день.

Решил изучить spring и попробовать сделать небольшое тестовое приложение.
Есть 2 сервиса, которые содержат друг друга и которые мне надо вытянуть из контекста спринга.

AuditoriumServiceImpl.java:
Код

public class AuditoriumServiceImpl extends GenericServiceImpl<Auditorium> implements IAuditoriumService{

    private IBuildingService buildingService;
    
    public AuditoriumServiceImpl() {
        super(Auditorium.class);    
    }

    public void setBuildingService(IBuildingService buildingService) {
        this.buildingService = buildingService;
    }

    public IBuildingService getBuildingService() {
        return buildingService;
    }
}


BuildingServiceImpl.java
Код

public class BuildingServiceImpl extends GenericServiceImpl<Building> implements IBuildingService {

    private IAuditoriumService auditoriumService;

    public BuildingServiceImpl(){
        super(Building.class);    
    }

    public void setAuditoriumService(IAuditoriumService auditoriumService) {
        this.auditoriumService = auditoriumService;
    }

    public IAuditoriumService getAuditoriumService() {
        return auditoriumService;
    }
}
 

spring-context.xml
Код

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> 
  
 
  <bean id="emf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="persistenceUnit" />
  </bean>
    
  <bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
    <property name="entityManagerFactory" ref="emf" />
  </bean>
  
  <bean name="buildingService" class="com.pk.service.impl.BuildingServiceImpl">
          <property name="jpaTemplate" ref="jpaTemplate" />    
          <property name="auditoriumService" ref="auditoriumService"></property>    
  </bean>
  
  <bean name="auditoriumService" class="com.pk.service.impl.AuditoriumServiceImpl">
        <property name="jpaTemplate" ref="jpaTemplate" />  
        <property name="buildingService" ref="buildingService" />     
  </bean>
</beans>


При вызове 
Код

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
        IBuildingService serv = (IBuildingService) applicationContext.getBean("buildingService");


выдает следующее исключение:
Код

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'buildingService': Bean with name 'buildingService' has been injected into other beans [auditoriumService] in its raw version as part of a circular reference, but has eventually been wrapped (for example as part of auto-proxy creation). This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:464)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:383)
    java.security.AccessController.doPrivileged(Native Method)


В нете читал что данный эксепшен возникает из-за циклической зависимости бинов, созданных через конструкторы. 
Я же использую сеттеры. возможно я что-то недопонял, с английским у меня не ахти...

Заранее спасибо.

Автор: DKroshkin 29.4.2010, 12:46
А зачем тебе зависимость одного бина от другого? buildingService от auditoriumService и наоборот

Как вариант сделать бины независимыми, и в каждом сделать реализацию ApplicationContextAware интерфейса, чтобы в любой момент можно было вытащить другой бин из контейнера.

Автор: anti_snayper 29.4.2010, 13:37
Надо будет попробовать...
Но все-таки почему эксепшен вылетает интересно. По идее, спринг должен создать пустые модели и потом просетать в них ссылки друг на друга.

Автор: DKroshkin 29.4.2010, 14:11
Вроде при инициализации контейнера, если не стоит lazy-init, и бины объявлены не как синглтоны, то спринг создает бины:
либо через конструктор, либо через сеттеры (возможно что можно сделать и симбиоз). Вот здесь то и происходит рекурсия.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)