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