Spring Prototype范围和实现特定属性

时间:2013-09-19 19:15:03

标签: spring jdbc configuration jms distributed-system

我正在设计一个支持分片和复制的分布式数据仓库。现在让我们假设我有一个管理器应用程序,它维护属于数据库表(在某些“主”数据库中)某处的数据仓库的所有数据库实例的“列表”及其类型,例如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,但它看起来不适合我的用例。

谢谢!

乔瓦尼

1 个答案:

答案 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填写每个数据库行的正确属性。