我正在使用Spring Data JPA开发一个项目。
我设法使用 BeanFactoryPostProcessor 动态创建数据源,并在使用 AbstractRoutingDataSource 登录时切换到所需的数据源。
现在我想在运行时做的是:
springContext-jpa.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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
............
>
<!--
...
...
Spring Data JPA config
...
...
-->
<!-- Parent abstract Datasource -->
<bean id="BasicdsCargestWeb" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- Generic Datasource -->
<bean id="dsCargestWeb" class="com.cargest.custom.CargestRoutingDataSource">
<property name="targetDataSources">
<map>
</map>
</property>
<property name="defaultTargetDataSource" ref="cargestnet1ds" />
</bean>
</beans>
DatasourceRegisteringBeanFactoryPostProcessor.java
@Component
class DatasourceRegisteringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// this is my list of Datasources
List<Database> dbs = new ArrayList<Database>();
/*
* Hidden code, here i get my list of Datasources
*/
BeanDefinitionRegistry factory = (BeanDefinitionRegistry) beanFactory;
BeanDefinitionBuilder datasourceDefinitionBuilder;
for (Database db : dbs) {
datasourceDefinitionBuilder = BeanDefinitionBuilder
.childBeanDefinition("BasicdsCargestWeb")
.addPropertyValue("url", db.getUrl()+db.getName()+"?autoReconnect=true");
factory.registerBeanDefinition("cargestnet"+db.getId()+"ds",
datasourceDefinitionBuilder.getBeanDefinition());
}
// Configure the dataSource bean properties
MutablePropertyValues mpv = factory.getBeanDefinition("dsCargestWeb").getPropertyValues();
// Here you can set the default dataSource
mpv.removePropertyValue("defaultTargetDataSource");
mpv.addPropertyValue("defaultTargetDataSource",
new RuntimeBeanReference("cargestnet1ds"));
// Set the targetDataSource properties map with the list of connections
ManagedMap<String, RuntimeBeanReference> mm = (ManagedMap<String, RuntimeBeanReference>) mpv.getPropertyValue("targetDataSources").getValue();
System.out.println("list size "+mm.size());
mm.clear();
for (Database db : dbs) {
mm.put(db.getId().toString(), new RuntimeBeanReference("cargestnet"+db.getId()+"ds"));
}
}
}
问题是 BeanFactoryPostProcessor 类使用 ConfigurableListableBeanFactory 作为beanFactory。
我需要从另一个类(在运行时)访问同一个beanFactory,以便修改我的数据源映射(dsCargestWeb - &gt; targetDataSources - &gt; map)。
由于
答案 0 :(得分:0)
我认为您可以尝试以下架构:
DataSourceS
AbstractRoutingDataSource
实现包含DataSourceS
的地图,最初注入上面的工厂bean 这样,如果您以后需要添加新的DataSource
,您可以从AbstractRoutingDataSource
实施中获取地图并将其直接添加到地图中,或者在{{1实现添加新的AbstractRoutingDataSource
。
作为上述变体,您可以创建一个类似的DataSource
实现,并使用它注入另一个bean,在AbstractRoutingDataSource
计算init-method
映射并在其中进行strores路由数据源。
答案 1 :(得分:-1)
使用RuntimeBeanReference
和ManagedSet
,您可以将运行时设置为beanDefine
。这是使用这些的正确方法:
ManagedSet<RuntimeBeanReference> processorSet = new ManagedSet<RuntimeBeanReference>();
for (String processorBeanName : processorBeanNames) {
processorSet.add(new RuntimeBeanReference(processorBeanName));
}
beanDefine.getPropertyValues().addPropertyValue(new PropertyValue(key, value));