通过AbstractRoutingDataSource实现动态数据源
- - 编程语言 - ITeye博客项目中用到了动态数据源,所以在这里做下记录. AbstractRoutingDataSource中route是路由的意思,单从名字,我们就可以看出这个类是做什么用的. 动态数据源是指,同一个数据库访问接口,根据上下文不通,可以利用不同的数据源访问数据库. 项目中采用了spring jdbc来访问数据库,配置文件如下:.
项目中用到了动态数据源,所以在这里做下记录。
AbstractRoutingDataSource中route是路由的意思,单从名字,我们就可以看出这个类是做什么用的
动态数据源是指,同一个数据库访问接口,根据上下文不通,可以利用不同的数据源访问数据库。 项目中采用了spring jdbc来访问数据库,配置文件如下:
<!--sqlMapClient配置--> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="xxxxxx" /> </bean> <!--数据源配置--> <bean id="dataSource" class="继承类AbstractRoutingDataSource"> <property name="targetDataSources"> <!--配置多个数据源--> </property> </bean>
spring中提供了类AbstractRoutingDataSource来实现动态数据源,这个类实现了DataSource接口,getConnection()方法如下:
public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); } 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; }
在getConnection方法中又调用了方法determineTargetDataSource,在这个方法中,只是返回一个数据源对象,但是返回哪个数据源对象呢,玄机在Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());
这行代码,我们可以在自己的实现类中去定制这个方法,根据自己的要求来确定具体返回哪一个数据源对象
每一次DAO接口调用,都会有一个线程上下文,我可以把需要使用哪一个数据源的信息放到线程变量中,然后再AbstractRoutingDataSource的实现类中,我可以像下面那样重写determineCurrentLookupKey方法
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); @Override protected Object determineCurrentLookupKey() { return contextHolder.get(); }
这样每个线程间相互隔离,也不会担心线程安全问题