现在随着软件项目的越来越大、靠一个集中式的项目已经无法满足并发量。 如果说数据量特别大就需要进行分库。这是最基本的策略,比如按照省份分库、某几个省分为一个域。一个域对应一个物理数据库。
分域如下:
一域:北京、上海
二域:河南、宁夏
三域:山西、吉林
四域:广东、四川
===========================================================================
那我们项目中启一套程序怎么实现这种数据源的动态切换呢?
假设项目中已经实现了动态数据源切换?那我们总的有一个依据、省份编码就是一个很好的字段。根据请求中带来的:省份编码、IP信息、交易流水等都可以作为 切换数据源的依据。
思路上通了以后就看需要怎么样的技术才能实现数据源的切换呢?
org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
里面有一个抽象方法
protected abstract Object determineCurrentLookupKey();
抽象方法就是自己只定义 不实现,让子类实现抽象方法赋值、然后返回到父类中。
//仔细看一下这个抽象方法返回的是个什么东西
protected DataSource determineTargetDataSource()
{
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
//抽象方法返回的 一个数据源的key 也就是Spring中注入数据源的一个Map集合的key
Object lookupKey = determineCurrentLookupKey();
//根据key得到数据源 配置 Spring中注入数据源的一个Map集合的key 对应的value
DataSource 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; }
///////////////继续往下看这个dataSource返回给谁了////////////////////
AbstractRoutingDataSource 抽象类里面的方法
public Connection getConnection()throws SQLException { return determineTargetDataSource().getConnection(); } public Connection getConnection(String username, String password) throws SQLException { return determineTargetDataSource().getConnection(username, password); }
//找到AbstractRoutingDataSource 的父类、父类里面没有这两个方法。
public abstract class AbstractRoutingDataSource extends AbstractDataSource
//父类AbstractDataSource 实现了一个DataSource接口
public abstract class AbstractDataSource implements DataSource{ } //在DataSource接口里面定义了这两个方法。 public interface DataSource extends CommonDataSource,Wrapper { Connection getConnection() throws SQLException; Connection getConnection(String username, String password) throws SQLException; }
AbstractRoutingDataSource实现了InitializingBean类,实现了afterPropertiesSet方法.afterPropertiesSet方法在bean的属性赋值之后执行,
并检查targetDataSources 是否有值,如果有值就将targetDataSources 转换成
resolvedDataSources.也就是说,如果你要使用AbstractRoutingDataSource,就必须在方法afterPropertiesSet执行之前,进行targetDataSources 属性的初始化.这也就是目前网上的配置方式,在配置文件里配置N个数据源的由来.
【扩展阅读 afterPropertiesSet 方法什么时候执行】
http://www.iteye.com/topic/1046993
===============================================
所有准备工作作为之后。写一个AOP的拦截到请求,解析请求中的省份编码。实现数据源切换。
整理一下代码。稍后会放到Git上 实现是Spring MVC + Mybatis环境。