我正在使用带有 DBCP 的 Spring,并且当操作环境的某些配置发生更改时需要刷新我的数据源,而无需重新启动所有应用程序。
如果我在不使用 DBCP 的情况下执行此操作,我会强制此刷新关闭当前打开的正在使用的数据源并启动一个新的 DataSource 实例。
使用 DBCP+Spring,我做不到。
有人知道这是否可能?
我正在使用带有 DBCP 的 Spring,并且当操作环境的某些配置发生更改时需要刷新我的数据源,而无需重新启动所有应用程序。
如果我在不使用 DBCP 的情况下执行此操作,我会强制此刷新关闭当前打开的正在使用的数据源并启动一个新的 DataSource 实例。
使用 DBCP+Spring,我做不到。
有人知道这是否可能?
我不认为普通 DBCP 有这样的支持,主要是因为数据库连接属性在应用程序的生命周期中很少改变。此外,您还必须考虑转换时间,即旧数据源提供的某些连接仍处于打开状态,而其他连接已经从新的(刷新的)数据源提供。
我建议您使用装饰器/代理设计模式编写DataSource的自定义实现。您的实现将简单地调用目标数据源(由 DBCP 创建),大部分时间什么也不做。但是当您调用某种refresh()
方法时,您的装饰器将关闭先前创建的数据源并使用新的配置创建新的数据源。记住多线程!
@Service
public class RefreshableDataSource implements DataSource {
private AtomicReference<DataSource> target = new AtomicReference<DataSource>();
@PostConstruct
public void refresh() {
target.set(createDsManuallyUsingSomeExternalConfigurationSource());
}
@Override
public Connection getConnection() throws SQLException {
return target.get().getConnection();
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return target.get().getConnection(username, password);
}
//Rest of DataSource methods
}
该createDsManuallyUsingSomeExternalConfigurationSource()
方法可能如下所示:
private DataSource createDsManuallyUsingSomeExternalConfigurationSource() {
DataSource ds = new org.apache.commons.dbcp.BasicDataSource();
ds.setDriverClassName("org.h2.Driver");
ds.setUrl(/*New database URL*/);
ds.setUsername(/*New username*/);
ds.setPassword(/*New password*/);
return ds;
}
这是 Spring bean 的粗略等价物:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
您不能只将这样的目标 bean 注入您的代理/装饰器RefreshableDataSource
,因为您希望数据源配置是动态/可刷新的,而 Spring 只允许您注入静态属性。这意味着创建 target 实例是您的责任BasicDataSource
,但正如您所见,这并不可怕。
实际上,我有第二个想法:Spring SpEL AFAIK 允许您从 XML 配置中调用其他 bean 的方法。但这是一个非常广泛的话题。
另一种方法可能是使用 JNDI 来获取DataSource
和使用热部署(它适用于 JBoss 及其*-ds.xml
文件。