2016-04-28 8 views
1

Моего ApiConfig:Невозможно @autowired репозиторий. Bean циклическая ссылка

@Configuration 
@EnableConfigurationProperties(JpaProperties.class) 
@EnableJpaRepositories("com.foo.api.persistence") 
@ComponentScan("com.foo.api") 
@PropertySource("classpath:application.yaml") 
public class ApiConfig { 

private static final Logger LOGGER = LogManager.getLogger(); 
private static final String MODEL_PACKAGE = "com.foo.api.model"; 

@Autowired 
private MultiTenantConnectionProviderImpl multiTenantConnectionProvider; 

@Autowired 
private ApplicationContext applicationContext; 

@Resource 
private org.springframework.core.env.Environment env; 

@Bean 
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws CurrentTenantIdentifierResolverException { 
    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 
    entityManagerFactoryBean.setPackagesToScan(MODEL_PACKAGE); 
    entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class); 

    Properties jpaProperties = new Properties(); 
    jpaProperties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA); 
    jpaProperties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider); 
    jpaProperties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, getCurrentTenantIdentifierResolver()); 
    jpaProperties.put(Environment.DIALECT, getHibernateDialect()); 

    entityManagerFactoryBean.setJpaProperties(jpaProperties); 

    return entityManagerFactoryBean; 
} 

private CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() throws CurrentTenantIdentifierResolverException { 
    CurrentTenantIdentifierResolver resolver = applicationContext.getBean(CurrentTenantIdentifierResolver.class); 
    if (resolver == null) { 
     throw new CurrentTenantIdentifierResolverException(); 
    } 

    return resolver; 
} 

private String getHibernateDialect() { 
    return env.getProperty(PropertyConstants.DIALECT); 
} 

}

Но теперь я не могу @Autowired моя JpaRepository:

@Autowired 
    private AgreementPersistence agreementPersistence; 

Соглашение живучесть просто репо простирается от JpaRepository одним собственного метода, основанного запроса ;

журнал Исключение:

Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: 

Could not autowire field: AgreementPersistence agreementPersistence; nested exception is org.springframework.beans.factory.BeanCreationException: 

Error creating bean with name 'agreementPersistence': Cannot create inner bean '(inner bean)#38830ea' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: 

Error creating bean with name '(inner bean)#38830ea': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: 

Error creating bean with name 'entityManagerFactory': Requested bean is currently in creation: Is there an unresolvable circular reference? 

Как это исправить? Может быть, я могу установить порядок создания бина или что-то еще?

Также: Мне нужно @Autowired repo в классе конфигурации другого модуля.

+0

Пожалуйста, добавьте стек ошибки инициализации Spring к вашему вопросу, чтобы было более ясно, что я буду делать с ошибкой '@Autowired'. –

+0

попробуйте вызвать метод entityManagerFactoryBean.afterPropertiesSet() – shazin

+0

Похоже, вы пытаетесь автосогласовать 'соглашениеPersistence' в класс, отвечающий за настройку JPA. Можете ли вы поделиться более подробной информацией о своих классах '@ Configuration'? –

ответ

0

В моем случае я использую два класса конфигурации java в двух разных модулях. Вначале я пишу пользовательский логин фабрики сущностей, а в другом я пытаюсь авторизовать мое собственное сохранение, расширяя JpaRepository. Во втором классе конфигурации я создаю собственный конфигурационный компонент, в котором я использую автообновленное репо. Поэтому у меня была неразрешимая циркулярная ссылка.

Я работаю с ним, добавив репозиторий аргумент в моей конфигурации фасоли, как это:

@Bean 
Foo foo(RepoThatIWantToAutowired repo) { ... } 

Может быть, это может помочь кого-то.

0

Вы в конечном итоге инициализируете свои репозитории JPA несколько раз. Попробуйте это:

@ComponentScan(
    value = "com.foo.api", 
    excludeFilters ={ 
      //@Repository beans are scanned and created by @EnableJpaRepositories already 
      @ComponentScan.Filter(Repository.class) 
    } 

)

+0

Это не поможет; Я думаю, что я получаю проблему, когда весна пытается автоуведомленному репо с внутренней компонентой EntityManager, когда EntityManagerFactory находится в создании; – DamienMiheev

2

Круговой ссылка, когда у вас есть два зерна, каждый впрыскивается в другой.

@Service 
public class A { 
    @Inject 
    private B b; 
} 

@Service 
public class B { 
    @Inject 
    private A a; 
} 

С весны не может привнести что-то, что не полностью инстанцированный, она не может вводить A в B до того B впрыскивается в A, и наоборот, что делает Spring застрял.

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

@Service 
public class C { 
    @Inject 
    private A a; 
    @Inject 
    private B b; 
} 

Если вы не можете разложить выход из него, это один из способов решения проблемы:

@Service 
public class A { 
    @Inject 
    private B b; 
} 

@Service 
public class B extends ApplicationContextAware { 
    //no inject 
    private A a; 

    private ApplicationContext applicationContext; 

    public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException { 
     this.applicationContext = applicationContext; 
    } 

    @PostConstruct 
    public void handleDependencies() { 
     this.a = applicationContext.getBean(A.class); 
    } 
} 
+0

У меня все еще такая же проблема. У меня есть conf1 в модуле 1 (компонентное сканирование «com.foo.mod1», где i init entityManagerFactoryBean; Также у меня есть conf2 в модуле2 (компонентное сканирование «com.foo.mod2»; Module2 compile dependencie to module1 in build.gradle В conf2 I @Import (Conf1.class); Но когда я попытался получить bean-компонент из appCtx, у меня есть то же исключение. – DamienMiheev

1

Try добавить @Lazy в entityManagerFactory или AgreementPersistence (класс, который весной жалуется на то, что не может быть введена).

Я считаю, что это предотвратит весну, чтобы на самом деле пытаться вставить «пружинный настроечный» компонент до тех пор, пока он не понадобится. Он должен сначала ввести исходный класс, чтобы удовлетворить зависимость и настроить весну позже.

+0

это решило мою проблему, спасибо. –

Смежные вопросы