Spring实现多数据源配置的思想和使用方式
实际的项目中,经常会用到不同的数据库以满足项目的实际需求。为了解决在不同的类中注入相同类型的数据库连接对象JdbcTemplate,而在真正使用的时候根据会自己的要求,分别使用不同的数据库连接的问题。就要使用到Spring管理多数据源的一种思想。
关于Connection,我们从jdbcTemplate的实际执行的execute方法为入口,观察代码的走向,
看到这里,你会发现,JdbcTempalte获取的连接就是根据我们给定的DataSource进行方法的调用,没有什么复杂的逻辑,那么配置多数据源无疑就要从getConnetion为入口。打开Ctrl_T 你可以看到许多不同的数据库连接的实现。因为我们需要按照我们自己的逻辑去实现获取不同的数据源,所以我们需要扩展这个方法按照我们的业务进行操作。所以你完全可以自己继承DataSource并封装一个Map作为数据源的保存,然后在覆写其中获取连接的方法满足自己的业务要求即可。
当然,为了避免反复造轮子,我们使用spring已经提供的AbstractRoutingDataSource抽象可扩展的类实现我们的逻辑。
-->解决思路:使用spring提供的多数据源思想结合AOP进行动态配置,ThreadLocal进行动态数据存储。
①:继承AbstractRoutingDataSource,实现自定义配置多数据源;
该类中使用Map进行多数据源的存储,并根据key获取对应的数据源,并提供默认的数据源。
在实际获取连接的方法中,该类为我们提供一个获取key的抽象方法我们可以自己去实现业务。
②:创建一个ThreadLocal变量用于存储不同的数据源Key;
从如上的介绍中我们看出,因为我们需要实现上面的抽象方法以获得不同情况下给出不同的key,所以我们可以使用本地变量进行操作不用考虑线程安全的问题,在线程访问方法之前设置这一变量,而这里仅仅只需要取出变量即可。可以起到一个很好的存储过渡的作用。(关于ThreadLocal的增删这里不做描述,可参考之前的博客)
③:使用AOP进行业务条件下的动态数据源设置;
最后,因为本文中我们假定select和insert分别使用不同的数据库,所以我们使用AOP在执行不同方法之前进行不同设置即可。
切面方法的伪代码如下:
最后在spring中进行AOP的配置,分别拦截seelct开头和insert开头的方法,配置不同的切面方法去设置不同的ThreadLocal值即可达到我们的要求。
④:根据不同的需求进行规范的代码编写,每一个业务要求不同,所以跟对自己的要求编写合理的代码是最重要的,主要是分享一下常规的思路,笔者也会不断发现更好的思路以分享给大家。