您的位置:首页 > 其它

利用AbstractRoutingDataSource实现动态数据源切换

2014-02-07 09:40 453 查看
转载自:http://dsbjoe.iteye.com/blog/1176779

最近要为公司多个游戏做类似的统计功能,考虑到模块的复用性,决定做个动态数据源,根据不同的游戏参数切换不同的datasource。

网上查了下,spring2.0以后增加了AbstractRoutingDataSource这个东西。下面是实现方法

首先看下AbstractRoutingDataSource类结构,继承了AbstractDataSource

Java代码


public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {

}

既然是AbstractDataSource,当然就是javax.sql.DataSource的子类,于是我们自然地回去看它的getConnection方法:

Java代码


public Connection getConnection() throws SQLException {

return determineTargetDataSource().getConnection();

}

原来奥妙就在determineTargetDataSource()里:

Java代码


/**

* Retrieve the current target DataSource. Determines the

* {@link #determineCurrentLookupKey() current lookup key}, performs

* a lookup in the {@link #setTargetDataSources targetDataSources} map,

* falls back to the specified

* {@link #setDefaultTargetDataSource default target DataSource} if necessary.

* @see #determineCurrentLookupKey()

*/

protected DataSource determineTargetDataSource() {

Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");

Object lookupKey = determineCurrentLookupKey();

DataSource dataSource = (DataSource) this.resolvedDataSources.get(lookupKey);

if (dataSource == null) {

dataSource = this.resolvedDefaultDataSource;

}

if (dataSource == null) {

throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");

}

return dataSource;

}

这里用到了我们需要进行实现的抽象方法determineCurrentLookupKey(),该方法返回需要使用的DataSource的key值,然后根据这个key从resolvedDataSources这个map里取出对应的DataSource,如果找不到,则用默认的resolvedDefaultDataSource

Java代码


<bean id="onlineDynamicDataSource" class="com.xx.stat.base.dynamic.DynamicDataSource">

<property name="targetDataSources">

<map key-type="java.lang.String">

<entry key="xx" value-ref="dataSourceXX"/>

<entry key="yy" value-ref="dataSourceYY"/>

</map>

</property>

<property name="defaultTargetDataSource" ref="dataSource"/>

</bean>

观察上面的配置文件,发现我们配置的是targetDataSources和defaultTargetDataSource

Java代码


public void afterPropertiesSet() {

if (this.targetDataSources == null) {

throw new IllegalArgumentException("targetDataSources is required");

}

this.resolvedDataSources = new HashMap(this.targetDataSources.size());

for (Iterator it = this.targetDataSources.entrySet().iterator(); it.hasNext();) {

Map.Entry entry = (Map.Entry) it.next();

Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());

DataSource dataSource = resolveSpecifiedDataSource(entry.getValue());

this.resolvedDataSources.put(lookupKey, dataSource);

}

if (this.defaultTargetDataSource != null) {

this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);

}

}

下面就是我们自己实现的子类DynamicDataSource

Java代码


public class DynamicDataSource extends AbstractRoutingDataSource{

@Override

public void setTargetDataSources(Map targetDataSources) {

super.setTargetDataSources(targetDataSources);

}

@Override

public Object unwrap(Class iface) throws SQLException {

return null;

}

@Override

public boolean isWrapperFor(Class iface) throws SQLException {

return false;

}

@Override

protected Object determineCurrentLookupKey() {

String dataSourceName = DynamicDataSourceHolder.getDataSourceName();

return dataSourceName;

}

DynamicDataSourceHolder

Java代码


public class DynamicDataSourceHolder {

private static final ThreadLocal<String> holder = new ThreadLocal<String>();

public static void putDataSourceName(String name){

holder.set(name);

}

public static String getDataSourceName(){

return holder.get();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: