使用Spring + dbcp刷新DataSource [英] Refresh DataSource using Spring+dbcp

查看:205
本文介绍了使用Spring + dbcp刷新DataSource的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring和DBCP,并且当操作环境上的某些配置发生变化时需要刷新我的数据源,而不需要重新启动所有应用程序。

I'm using Spring with DBCP and need to refresh my datasource when some configuration on operation environment changes, without restart all application.

如果我这样做没有使用DBCP,我强制这个刷新关闭当前打开的数据源正在使用并启动一个新的DataSource实例。

If I do it with no use of DBCP, I force this refresh closing current opened datasource in use and Start a new instance of DataSource.

使用DBCP + Spring,我做不到。

Using DBCP+Spring, I can't do that.

有人知道是否可能吗?

推荐答案

我不知道认为在普通的DBCP中有这样的支持,主要是因为数据库连接属性在应用程序的生命周期中很少发生变化。此外,当旧数据源提供的某些连接仍然打开而其他连接已经从新的(刷新的)提供服务时,您将不得不考虑转换时间。

I don't think there is such a support in plain DBCP, mostly because database connection properties are very rarely changing during the lifetime of the application. Also you will have to consider transition time, when some connections served by the old data source are still opened while others are already served from the new (refreshed) one.

我建议你编写 DataSource 。您的实现只需调用目标数据源(由DBCP创建),大多数情况下不会执行任何操作。但是当你调用某种 refresh()方法时,装饰器将关闭先前创建的数据源,并使用全新配置创建新数据源。记住多线程!

I would suggest you to write custom implementation of DataSource leveraging Decorator/Proxy design pattern. Your implementation would simply call target data source (created by DBCP), most of the time doing nothing more. But when you call some sort of refresh() method, your decorator will close previously created data source and create new one with fresh configuration. Remember about multi-threading!

@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的粗略等价物:

This is a rough equivalent of 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只允许您注入静态属性。这意味着您有责任创建目标 BasicDataSource 的实例,但正如您所看到的,这并不可怕。

You can't just inject such a target bean into your proxy/decorator RefreshableDataSource as you want data source configuration to be dynamic/refreshable, while Spring only allows you to inject static properties. This means that it is your responsibility to create an instance of target BasicDataSource, but as you can see, it is nothing scary.

实际上,我还有第二个想法:Spring SpEL AFAIK允许您从XML配置中调用其他bean的方法。但这是一个非常广泛的主题。

Actually, I have a second thought: Spring SpEL AFAIK allows you to call other beans' methods from XML configuration. But this is a very wide topic.

另一种方法可能是使用JNDI来获取 DataSource 并使用热部署(它适用于JBoss及其 * - ds.xml 文件。

Another approach might be to use JNDI to fetch DataSource and use hot-deployment (it works with JBoss and its *-ds.xml files.

这篇关于使用Spring + dbcp刷新DataSource的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆