今天研究项目的多数据源配置,产生了一点疑惑,有很多地方没有指定数据源,那么spring如何知道连接哪一个呢?让我们从头开始梳理吧。
首先是数据源配类
其中使用到了两个数据源,项目采用读写分离,一个主库和一个从库,主写从读,提高并发性能。@Primary注解的作用是优先使用这个bean,并且在启动类@SpringBootApplication中设置排除掉DataSourceAutoConfiguration.class,因为springboot项目会自动加载。然后是动态数据源配置类。
如图,我们用ThreadLocal来存储数据源类型,并且设置切面。切面如下
大概的逻辑就是,在所用使用了@DataSource注解的地方进行aop,取出注解的值(不存在则默认为master),将值设置进去,完成数据源的切换。那么问题来,我看很多地方并没有使用到@DataSource这个注解,那么spring是如何选择相应的数据源的呢?再次分析代码,发现DynamicDataSource中重写了父类determineCurrentLookupKey()方法,这个方法就是返回查找当前数据源的key。在构造DynamicDataSource时我们传入了默认数据源,和一个存储所有可选数据源的map,我们可以根据这个key去定位具体想使用的数据源。
点击进入父类方法,发现真正决策出数据源的方法是determineTargetDataSource()。它首先判断所有可选数据源map不为空,然后调用我们重写的determineCurrentLookupKey()方法找出当前数据源的key,如果这个key为null或者通过key在map中查找的数据源为null,则使用默认数据源
默认的数据源就是我们一开始构造DynamicDataSource传入的,
defaultTargetDataSource就是我们传入的master数据源,这里通过resolveSpecifiedDataSource()做了一层适配,如果defaultTargetDataSource是dataSource类型则直接返回,如果不是则把它当成key去所有可选数据源map中查。这里不得不说spring的作者真牛啊,方方面面都考虑到了。
通过这一通分析下来,这才解开最开始的问题,为什么很多地方没有指定数据源,甚至没有通过切面,也可以找到数据源。因为不指定用的都是默认的数据源,只需要在用到其他数据源的地方指定就可以了,我们只需要完成数据源的初始化编写工作即可。