`
风过无声
  • 浏览: 88067 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

AbstractRoutingDataSource动态切换数据源

 
阅读更多

1.使用

1)写一个DynamicDataSource类继承AbstractRoutingDataSource

public class DynamicDataSource extends AbstractRoutingDataSource {

	@Override
	protected Object determineCurrentLookupKey() {
		return DSNameHolder.getDSName();
	}
	
	/**
	 * used for test
	 * @return
	 */
	public DataSource getCurrentDataSource() {
		return super.determineTargetDataSource();
	}
	
}

2) DSNameHolder

public class DSNameHolder {
	
	public static ThreadLocal<String> DS_NAME_HOLDER = new ThreadLocal<String>();
	   
	public static void setDSName(String dsName) {
		DS_NAME_HOLDER.set(dsName);
	}
	
	public static String getDSName() {
		return DS_NAME_HOLDER.get();
	}
	
}

3)测试

spring-ds.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
        
    <bean name="datasource" class="com.siyuan.study.spring.jdbc.DynamicDataSource">
        <property name="targetDataSources">
            <map>
                <entry key="ds_a" value-ref="datasource_a"/>
                <entry key="ds_b" value-ref="datasource_b"/>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="datasource_a"/>
    </bean>

	<bean id="datasource_a"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="url" value="jdbc:mysql://localhost:3306;databaseName=test_a" />
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="username" value="root" />
		<property name="password" value="123456" />
	</bean>

    <bean id="datasource_b"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql://localhost:3306;databaseName=test_b" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
    </bean>
    
</beans>

DynamicDataSourceTest

public class DynamicDataSourceTest {
	
	private ApplicationContext ctxt;
	
	@Before
	public void setup() {
		ctxt = new ClassPathXmlApplicationContext("spring-ds.xml");
	}
	
	@Test
	public void getConnection() {
		DynamicDataSource datasource = (DynamicDataSource) ctxt.getBean("datasource"); 
		DataSource datasource_a = (DataSource) ctxt.getBean("datasource_a");
		DataSource datasource_b = (DataSource) ctxt.getBean("datasource_b");
		assertSame(datasource_a, datasource.getCurrentDataSource());
		//switch to ds_b
		DSNameHolder.setDSName("ds_b");
		assertSame(datasource_b, datasource.getCurrentDataSource());
		//switch to ds_a
		DSNameHolder.setDSName("ds_a");
		assertSame(datasource_a, datasource.getCurrentDataSource());
	}
	
}

2.源码分析

1)afterPropertiesSet

public void afterPropertiesSet() {
	if (this.targetDataSources == null) {
		throw new IllegalArgumentException("Property 'targetDataSources' is required");
	}
	this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size());
	for (Map.Entry entry : this.targetDataSources.entrySet()) {
		Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());
		DataSource dataSource = resolveSpecifiedDataSource(entry.getValue());
		this.resolvedDataSources.put(lookupKey, dataSource);
	}
	if (this.defaultTargetDataSource != null) {
		this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);
	}
}

2)getConnection

public Connection getConnection() throws SQLException {
	return determineTargetDataSource().getConnection();
}

public Connection getConnection(String username, String password) throws SQLException {
	return determineTargetDataSource().getConnection(username, password);
}

3)determineTargetDataSource

protected DataSource determineTargetDataSource() {
	Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
	Object lookupKey = determineCurrentLookupKey();
	DataSource dataSource = this.resolvedDataSources.get(lookupKey);
	if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
		dataSource = this.resolvedDefaultDataSource;
	}
	if (dataSource == null) {
		throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
	}
	return dataSource;
}

3.参考资料

http://blog.163.com/wang_hj138@126/blog/static/140800106201263151242338/

http://www.360doc.com/content/13/1016/15/14212114_321868950.shtml

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics