我的ApiConfig
:
@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扩展repo;
异常日志:
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?
如何解决? 也许我可以设置一些bean创建顺序或其他什么?
同时 我需要在另一个模块的配置类中使用@Autowired repo。
答案 0 :(得分:3)
循环引用是指有两个bean,每个bean都注入另一个bean。
@Service
public class A {
@Inject
private B b;
}
@Service
public class B {
@Inject
private A a;
}
由于Spring无法注入未完全实例化的内容,因此在将A
注入B
之前,它无法将B
注入A
反之亦然,从而使Spring陷入困境。
在这些情况下,您应首先分析,看看是否确实需要循环依赖。也许将bean分解成这样的东西是你真正需要的:
@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);
}
}
答案 1 :(得分:1)
尝试将@Lazy
添加到entityManagerFactory
或AgreementPersistence
(春天抱怨无法注入的课程)。
我相信它会阻止spring实际上尝试注入“spring-configured”bean,直到实际需要它为止。它应首先注入原始类以满足依赖性并在以后进行弹簧配置。
答案 2 :(得分:0)
您最终会多次初始化JPA存储库。试试这个:
@ComponentScan(
value = "com.foo.api",
excludeFilters ={
//@Repository beans are scanned and created by @EnableJpaRepositories already
@ComponentScan.Filter(Repository.class)
}
)
答案 3 :(得分:0)
在我的情况下,我在两个不同的模块中使用两个java配置类。 首先我编写自定义实体管理器工厂bean,在另一个我尝试自动连接我自己的持久性扩展JpaRepository。 在第二个配置类中,我创建自己的配置bean,我使用autowired repo。所以我有无法解决的循环参考。
我通过在我的配置bean中添加存储库参数来使用它,如下所示:
@Bean
Foo foo(RepoThatIWantToAutowired repo) { ... }
也许这对某人有帮助。