0

我正在设计一个支持分片和复制的分布式数据仓库。现在让我们假设我有一个管理器应用程序,它维护属于数据库表(在某些“主”数据库中)某处的数据仓库的所有数据库实例的“列表”及其类型,例如 Oracle、MySql 等. 和凭证,例如服务器名称、用户名、密码、数据库名称等(注意,这也可以是分布式配置服务,如 Zookeeper)。我们还假设给定该表中的一行x,我希望能够在运行时为xDataSource创建一个本机对象,即,当管理器应用程序需要它时。我需要做的是读取数据库x的行从主数据库中,获取数据库的类型、其凭据并创建DataSource供应商提供的实现实例(我不想使用诸如此类DriverManagerDataSource的包装器)。我希望能够仅从配置中添加新的 JDBC 驱动程序,而无需重新编译。

现在这是我的实现想法。给定一个N个JDBC 驱动程序列表,我可以创建N个 Spring 原型 bean,一个DataSource,然后当我的应用程序需要数据库x的实例时,从N个原型之一创建一个新实例,然后为x设置正确的凭据。

这是棘手的部分:我不想为每个不同的驱动程序编写代码来执行上述操作。我想以某种方式将占位符放在我的 Spring 原型中,然后在运行时使用从数据库字段到本地DataSource设置器的映射填充它们。例如,我可以有两个原型,例如:

<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,但它看起来不适合我的用例。

谢谢!

乔瓦尼

4

1 回答 1

1

只是我的 2 美分:
您可以通过这种方式为每个 RDBMS 配置使用一个持有者 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从每个数据库行中填充正确的属性。

于 2013-09-20T05:22:11.990 回答