我正在尝试使用Spring的@Configuration
类在同一个应用程序上下文中配置多个JPA实体/事务管理器。
当上下文加载时,Spring很难自动连接bean,因为它们实现了相同的接口。
不幸的是,我使用的是遗留代码,因此我无法直接自动连接bean并使用@Qualifier
注释,这就是为什么我尝试使用配置类。
在@Bean
声明中,有没有办法确定应该注入哪个bean?我认为使用直接方法调用就足够了,但它通常会导致错误,例如
NoUniqueBeanDefinitionException:没有类型的限定bean 定义了[javax.sql.DataSource]:期望的单个匹配bean但是 发现4
这是我在下面尝试做的一个例子:
@Configuration
public class ApplicationConfig {
@Bean(name = "transactionManager1")
public PlatformTransactionManager transactionManager1() {
return new JpaTransactionManager(entityManagerFactory1());
}
@Bean(name = "entityManagerFactory1")
public EntityManagerFactory entityManagerFactory1() {
...
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource1());
...
}
@Bean(destroyMethod = "")
@ConfigurationProperties(prefix = "datasource.test1")
public JndiObjectFactoryBean jndiObjectFactoryBean1() {
return new JndiObjectFactoryBean();
}
@Bean(name = "dataSource1")
public DataSource dataSource1() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiObjectFactoryBean1().getJndiName());
}
@Bean(name = "transactionManager2")
public PlatformTransactionManager transactionManager2() {
return new JpaTransactionManager(entityManagerFactory2());
}
@Bean(name = "entityManagerFactory2")
public EntityManagerFactory entityManagerFactory2() {
...
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource2());
...
}
@Bean(destroyMethod = "")
@ConfigurationProperties(prefix = "datasource.test2")
public JndiObjectFactoryBean jndiObjectFactoryBean2() {
return new JndiObjectFactoryBean();
}
@Bean(name = "dataSource2")
public DataSource dataSource2() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiObjectFactoryBean2().getJndiName());
}
我想我可以尝试通过Spring上下文的getBean()方法直接注入bean,但有没有更简洁的方法呢?
我对@Primary注释并不太熟悉,但根据我所读到的内容,我不知道在这种情况下spring会如何自动装配辅助数据源,因为它看起来像总是先用@Primary挑选豆子。
答案 0 :(得分:0)
如果您无法更改注射网站以添加限定符,那么您将必须根据某些逻辑(您在问题中未详细说明)创建委派DataSource
。
像这样。
@Primary @Bean
public DelegatingDataSource delegatingDataSource(List<DataSource> sources) {
return new DelegatingDataSource() {
@Override
public DataSource getTargetDataSource() {
// decide which dataSource to delegate to
return sources.get(0);
}
}
}
我已使用DelegatingDataSource
,但可能无法满足您的需求。您可能需要使用某种拦截器/方面获得更高级的功能,以获取调用者的详细信息,以此作为数据源选择的基础。
无论如何实现,您需要指定一个@Primary
bean并将其用作代理。