mybatis动态切换数据源

(#)背景:由于业务的需求,导致需要随时切换15个数据源,此时不能low逼的去写十几个mapper,所以想到了实现一个数据源的动态切换

首先要想重写多数据源,那么你应该理解数据源的一个概念是什么,DataSourceTransactionManager这个类就是spring中对于数据源的封装,其中DataSource做为

他的一个成员.接下来我们要介绍一下我们切换动态数据源需要使用的类,AbstractRoutingDataSource,先来看看这个类的源码

首先看看这几个变量,targetDataSources代表的就是备选的数据源了,用一个map存储,显然是为了在关键的时候快速的查找这些数据源,defaultTargetDataSource

就是我们在配置的时候一般都会制定一个默认的数据源就是它了,

 

程序运行的时候在加载配置文件的时候,首先会执行setTargetDataSources方法,这个方法会加载配置文件中配置的数据源,存储在上面说的targetDataSource中,

然后是设置setDefaultTergetDataSource,这个就是上面说的默认的数据源,

接下来会执行这个方法,在其中会将所有的数据源用来初始化resolvedDataSources,而当实际上和数据库产生交互的时候那么会调用到下面的方法:

如果看到这里大概你也知道怎么回事了,在我们实际和数据库产生交互的时候那么就需要使用到数据源了,那么这个时候我们只是需要重写这determineCurrentLookupKey

方法,而用这个方法具体干了什么呢?就是用它来寻找数据源啊,也就是说我们在mapper中的配置:

(#)下面看看代码上怎么来写

首先为了线程安全我们使用一个ThreadLocal来做存储

public class ContextHolder {
    public static final String DATASOURCE_1="dataSource";
    public static final String DATASOURCE_2="dataSource2";

    private static final ThreadLocal<String> context = new ThreadLocal<String>();

    public static void setConsumerType(String consumerType){
        context.set(consumerType);
    }

    public static String getConsumerType(){
        return context.get();
    }

    public static void clearConsumerType(){
        context.remove();
    }
}

  

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return ContextHolder.getConsumerType();
    }
}

  其实剩下的怎么实现已经很简单了,基本思路就是使用一个动态代理,在执行这个方法的时候,我们动态的给ContextHoler设置值,我建议使用spring aop,或者如果

不是spring的项目,那么直接只用动态代理也是很好的我觉,下面贴出一些我的简陋的代码

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("execution(* com.wang.route.DynamicPersonService.*(..))")
    public void pointCut() {
    }


    @Before(value = "pointCut()")
    public void before(JoinPoint joinPoint) {
     
            ContextHolder.setConsumerTyp(“”);
        
    }
}

  

 

posted @ 2017-01-06 19:46  nasjjsadkef  阅读(17822)  评论(6编辑  收藏  举报