转:http://www.360doc.com/content/14/0305/16/16118748_357970326.shtml
最近要为公司多个游戏做类似的统计功能,考虑到模块的复用性,决定做个动态数据源,根据不同的游戏参数切换不同的datasource。
网上查了下,spring2.0以后增加了AbstractRoutingDataSource这个东西。下面是实现方法
首先看下AbstractRoutingDataSource类结构,继承了AbstractDataSource
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean { }
public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); }
/** * 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
<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>
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); } }
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; }
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(); } }