我正在设计一个支持分片和复制的分布式数据仓库。现在让我们假设我有一个管理器应用程序,它维护属于数据库表(在某些“主”数据库中)某处的数据仓库的所有数据库实例的“列表”及其类型,例如Oracle,MySql等。 。和凭证,例如服务器名称,用户名,密码,数据库名称等(请注意,这也可能是像Zookeeper这样的分布式配置服务)。我们还假设从该表中给出一行 x ,我希望能够在运行时为 x 创建一个本地DataSource
对象,即经理应用程序需要它。我需要做的是从master数据库中读取数据库 x 的行,获取数据库的类型,其凭据并创建供应商提供的DataSource
实现的实例(我不想使用诸如DriverManagerDataSource
之类的包装器。我希望能够仅从配置添加新的JDBC驱动程序,而无需重新编译。
现在这是我的实施想法。给定 N JDBC驱动程序列表,我可以创建 N Spring原型bean,每DataSource
一个,然后当我的应用程序需要数据库的实例时x ,从其中一个 N 原型创建一个新实例,然后为 x 设置正确的凭据。
这是一个棘手的部分:我不想编写代码来为每个不同的驱动程序执行上述 。我想以某种方式将占位符放在我的Spring原型中,然后在运行时使用从数据库字段到本地DataSource
setter的映射填充它们。例如,我可以有两个原型,例如:
<bean id="postgresDatasourcePrototype" scope="prototype"
class="org.postgresql.jdbc2.optional.SimpleDataSource">
<property name="serverName" value="${db.host}"/>
<property name="databaseName" value="${db.name}"/>
<property name="portNumber" value="${db.port}"/>
<property name="user" value="${db.user}"/>
<property name="password" value="${db.pwd}"/>
</bean>
<bean id="ingresDatasourcePrototype" scope="prototype"
class="com.ingres.jdbc.IngresDataSource">
<property name="serverName" value="${db.host}"/>
<property name="databaseName" value="${db.name}"/>
<property name="portName" value="${db.port}"/>
<property name="user" value="${db.user}"/>
<property name="password" value="${db.pwd}"/>
</bean>
我希望使用 x 行的参数绑定占位符。
请注意,虽然大多数JDBC驱动程序的属性相似,但(1)没有通用接口,(2)可能存在变化,例如上面的portNumber与portName。如果使用Spring没有开箱即用的方法,我唯一能想到的就是提供从 x 字段到每个JDBC数据源属性的映射。驱动程序(在配置时)然后使用反射来实际设置这些属性,这基本上是Spring在封面下所做的事情。
编辑:只是为了说清楚,可能有 N 不同的JDBC驱动程序,我可能需要为该驱动程序创建 M 不同的数据源实例,每个都有不同的凭据从不同的行 x 读取。
请注意,我想要一个通用解决方案,即它也适用于JMS ConnectionFactory
。
有没有办法用Spring做到这一点?我在看PropertyPlaceholderConfigurer,但它看起来不适合我的用例。
谢谢!
乔瓦尼
答案 0 :(得分:1)
只需2美分:
您可以通过这种方式为每个RDBMS配置使用holder bean,并使用spEL绑定值:
class RDBMSConfigBean {
String host;
String name;
String port;
String user;
String pwd;
/* All accessors */
}
class RDBMSConfigBeanHolder {
RDBMSConfigBean pgConfig;
RDBMSConfigBean ingresConfig;
/* All accessors */
}
<bean id="rdbmsConfigHolder" class="RDBMSConfigBeanHolder" />
<bean id="ingresDatasourcePrototype" scope="prototype" class="com.ingres.jdbc.IngresDataSource">
<property name="serverName" value="#{rdbmsConfigHolder.ingresConfig.host}"/>
<!-- other props -->
</bean>
在您的应用程序代码中,您可以@Autowire
rdbmsConfigHolder
填写每个数据库行的正确属性。