AbstractRoutingDataSource

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

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

 

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

Java代码 复制代码  收藏代码
  1. public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {   
  2.   
  3. }  
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {

}
 

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

Java代码 复制代码  收藏代码
  1. public Connection getConnection() throws SQLException {   
  2.     return determineTargetDataSource().getConnection();   
  3. }  
	public Connection getConnection() throws SQLException {
		return determineTargetDataSource().getConnection();
	}

 原来奥妙就在determineTargetDataSource()里:

Java代码 复制代码  收藏代码
  1. /**  
  2.  * Retrieve the current target DataSource. Determines the  
  3.  * {@link #determineCurrentLookupKey() current lookup key}, performs  
  4.  * a lookup in the {@link #setTargetDataSources targetDataSources} map,  
  5.  * falls back to the specified  
  6.  * {@link #setDefaultTargetDataSource default target DataSource} if necessary.  
  7.  * @see #determineCurrentLookupKey()  
  8.  */  
  9. protected DataSource determineTargetDataSource() {   
  10.     Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");   
  11.     Object lookupKey = determineCurrentLookupKey();   
  12.     DataSource dataSource = (DataSource) this.resolvedDataSources.get(lookupKey);   
  13.     if (dataSource == null) {   
  14.         dataSource = this.resolvedDefaultDataSource;   
  15.     }   
  16.     if (dataSource == null) {   
  17.         throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");   
  18.     }   
  19.     return dataSource;   
  20. }  
	/**
	 * 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代码 复制代码  收藏代码
  1. <bean id="onlineDynamicDataSource" class="com.xx.stat.base.dynamic.DynamicDataSource">   
  2.    <property name="targetDataSources">      
  3.       <map key-type="java.lang.String">      
  4.          <entry key="xx" value-ref="dataSourceXX"/>      
  5.          <entry key="yy" value-ref="dataSourceYY"/>      
  6.       </map>      
  7.    </property>      
  8.    <property name="defaultTargetDataSource" ref="dataSource"/>     
  9. </bean>  
    <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代码 复制代码  收藏代码
  1. public void afterPropertiesSet() {   
  2.     if (this.targetDataSources == null) {   
  3.         throw new IllegalArgumentException("targetDataSources is required");   
  4.     }   
  5.     this.resolvedDataSources = new HashMap(this.targetDataSources.size());   
  6.     for (Iterator it = this.targetDataSources.entrySet().iterator(); it.hasNext();) {   
  7.         Map.Entry entry = (Map.Entry) it.next();   
  8.         Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());   
  9.         DataSource dataSource = resolveSpecifiedDataSource(entry.getValue());   
  10.         this.resolvedDataSources.put(lookupKey, dataSource);   
  11.     }   
  12.     if (this.defaultTargetDataSource != null) {   
  13.         this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);   
  14.     }   
  15. }  
	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代码 复制代码  收藏代码
  1. public class DynamicDataSource extends AbstractRoutingDataSource{   
  2.        
  3.     @Override  
  4.     public void setTargetDataSources(Map targetDataSources) {   
  5.         super.setTargetDataSources(targetDataSources);   
  6.     }   
  7.        
  8.     @Override  
  9.     public Object unwrap(Class iface) throws SQLException {   
  10.         return null;   
  11.     }   
  12.   
  13.     @Override  
  14.     public boolean isWrapperFor(Class iface) throws SQLException {   
  15.         return false;   
  16.     }   
  17.   
  18.     @Override  
  19.     protected Object determineCurrentLookupKey() {   
  20.         String dataSourceName = DynamicDataSourceHolder.getDataSourceName();   
  21.         return dataSourceName;   
  22.     }  
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代码 复制代码  收藏代码
  1. public class DynamicDataSourceHolder {   
  2.   
  3.     private static final ThreadLocal<String> holder = new ThreadLocal<String>();   
  4.        
  5.     public static void putDataSourceName(String name){   
  6.         holder.set(name);   
  7.     }   
  8.        
  9.     public static String getDataSourceName(){   
  10.         return holder.get();   
  11.     }   
  12. }  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值