Я не думаю, что есть такая поддержка в простом DBCP, в основном потому, что свойства соединения с базой данных очень редко меняются в течение всего времени существования приложения.Также вам придется учитывать время перехода, когда некоторые соединения, обслуживаемые старым источником данных, все еще открыты, а другие уже обслуживаются из нового (обновленного).
Подход Decorator / proxy
Я бы посоветовал вам написать собственную реализацию DataSource , использующую шаблон проектирования Decorator / Proxy.Ваша реализация просто вызовет целевой источник данных (созданный 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;
}
Это грубый эквивалент bean-компонента Spring:
<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>
Вы не можете просто внедрить такой целевой бин в прокси / декоратор RefreshableDataSource
, так как вы хотите, чтобы конфигурация источника данных была динамической / обновляемой, в то время как Spring позволяет вводить только статические свойства.Это означает, что вы несете ответственность за создание экземпляра цели BasicDataSource
, но, как видите, в этом нет ничего страшного.
На самом деле у меня есть вторая мысль: Spring SpEL AFAIK позволяет вам вызывать методы других компонентов из конфигурации XML.Но это очень широкая тема.
Подход JNDI
Другой подход может заключаться в использовании JNDI для извлечения DataSource
и использования горячего развертывания (он работает с JBoss и его *-ds.xml
файлами.