Spring 动态创建并切换数据源
公司要求后端项目可以进行动态创建并切换数据源,看了网上很多例子大多数使用的都是Spring内置的AbstractRoutingDataSource进行的,使用此方法不是不行但是有诸多缺陷,比如切换时需要依赖其ThreadLocal作为依据才可以切换。
AbstractRoutingDataSource可以动态切换数据源的原理,实际上是通过determineCurrentLookupKey方法找出对应的dataSource并通过getConnection方法获取链接。简单来说就是就是从不同的数据源获取不同的数据库链接,由此可以使用另一种更简单的方法来完成。
AbstractRoutingDataSource继承了AbstractDataSource类,而AbstractDataSource类直接继承了DataSource类,所以说我们可以直接继承AbstractDataSource并重写getConnection方法来完成我们的目的。
1 public class DynamicDataSource extends AbstractDataSource { 2 private static Logger logger = LoggerFactory.getLogger(DynamicDataSource.class); 3 4 private DataSource dataSource; 5 6 public DynamicDataSource(@Autowired DruidConfiguration sqliteConfiguration) throws IOException { 7 dataSource = sqliteConfiguration.dataSource(); 8 } 9 10 @Override 11 public Connection getConnection() throws SQLException { 12 return dataSource.getConnection(); 13 } 14 15 public DruidDataSource getDataSource() { 16 return (DruidDataSource) dataSource; 17 } 18 19 public void changeDataSource(DruidDataSource newDataSource) { 20 this.dataSource = newDataSource; 21 } 22 23 @Override 24 public Connection getConnection(String username, String password) throws SQLException { 25 return getConnection(); 26 } 27 }
其中DynamicDataSource是我们自定义的java类,他继承了上边提到了AbstractDataSource,只需要实现两个getConnection方法即可。由于我没有用到带参数的getConnection方法,所以未对此方法进行处理。
只要理解了切换的原理是通过getConnection获取不同的数据库链接之后,其余的就很简单了。另外,与AbstractRoutingDataSource相同的一点是使用AbstractDataSource也需要注入一个默认的数据源,所以我在DynamicDataSource的构造方法中自动注入了一个默认的数据源。
经过上文的处理之后,项目启动之后会拥有一个默认的小型数据源(即一个初始的数据源)。当需要进行切换的时候只需要调用其中的changeDataSource方法即可。
示例:
@Autowired private DynamicDataSource dynamicDataSource; DruidDataSource sqlLiteDataSource = dictService.getOtrpDataSource(); dynamicDataSource.changeDataSource(sqlLiteDataSource);
其中sqlLiteDataSource中的数据来源于数据库,这样的话只需要在需要切换的地方读取并切换就可以了。