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