一、问题场景形容
在应用MyBatis-Plus的DynamicRoutingDataSource时遇到的问题,当我在配置核心动静减少或者删除了一个数据源,DynamicDataSourceProperties并没有进行刷新,导致新加的数据源未失效,须要重启服务能力读取到最新的数据源配置
二、问题产生的起因
在Spring Cloud中刷新Bean,官网提供了@RefreshScope注解用于Bean的刷新,然而DynamicDataSourceProperties并没有该注解,导致Spring容器中的Bean始终是工程启动时创立的缓存,那么就无奈拿到最新的配置,也就无奈通过配置核心去动静减少、删除数据源
三、解决思路
既然官网的DynamicDatasourceProperties没法做到主动刷新,那本人结构一个能刷新的配置不就行了吗?代码如下:
@Data@RefreshScope@ConfigurationProperties(DynamicDataSourceProperties.PREFIX)public class RefreshableDynamicDataSourceProperties implements DisposableBean { /** * 每一个数据源 */ private Map<String, DataSourceProperty> datasource = new LinkedHashMap<>(); @Override public void destroy() throws Exception { datasource = new LinkedHashMap<>(); }}
注:此处肯定要实现DisposableBean接口,并重置数据源,否则在配置核心删除数据源时没法失常删除,这是因为Spring源码中判断Bean的属性如果是复合类型如Map做的操作是putAll()操作,也就是说不会删除原来配置。
下面只是实现了第一步,上面还要将咱们本人的配置在配置刷新的时候退出到DynamicRoutingDataSource中,那么此时须要一个监听器去监听配置刷新的事件,代码如下:
@Order(0)@Configuration@RequiredArgsConstructor@ConditionalOnClass(DynamicDataSourceAutoConfiguration.class)@EnableConfigurationProperties(RefreshableDynamicDataSourceProperties.class)@AutoConfigureAfter({DataSourceAutoConfiguration.class, DynamicDataSourceAutoConfiguration.class})public class DynamicDataSourceConfig implements ApplicationListener<RefreshScopeRefreshedEvent> { private final RefreshableDynamicDataSourceProperties properties; private final DataSource dataSource; private final DefaultDataSourceCreator creator; @Override public void onApplicationEvent(RefreshScopeRefreshedEvent event) { //获取最新的数据源 Map<String, DataSourceProperty> datasource = properties.getDatasource(); //获取原来的数据源 DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource; //移除以后数据源中不存在的数据源 Set<String> keys = datasource.keySet(); //判断是否存在(不存在即删除) ds.getDataSources().entrySet().removeIf(next -> !keys.contains(next.getKey())); //增加新的数据源 datasource.forEach((key, value) -> { ds.addDataSource(key, creator.createDataSource(value)); }); }}
此时就实现了不重启工程的状况下动静利用配置核心数据源了。
四、总结
自己也是第一次遇到这种需要,记录一下本人的解决思路和计划,至于官网为什么没有加@RefreshScope实现配置主动刷新这就不得而知了。