解析配置文件自动装配 DataSource + Abstract

2018-11-13  本文已影响0人  DJN_

上篇文章中已经借助 DynamicDataSourceBuilder 类从配置文件中解析得到了默认数据源和动态数据源,接下来需要配置动态数据源的“本体”,并借助 AOP 动态的切换数据源。

配置动态数据源

AbstractRoutingDataSource 实现了 InitializingBean 接口,在 afterPropertiesSet方法中通过处理 targetDataSourcesdefaultTargetDataSource中得到最终的 resolvedDefaultDataSourceresolvedDataSources,我们的实现类(动态数据源“本体”)需要覆写该方法,从而给targetDataSourcesdefaultTargetDataSource进行赋值。

image.png
可以看到第 118 行如果 targetDataSources 为 null 就会抛出异常,因此我们的导出类需要先进行赋值,再调用父类方法,动态数据源配置代码如下:
@Component
public class DynamicDataSource extends AbstractRoutingDataSource {

    private static final ThreadLocal<DsKey> dataSourceKey = new InheritableThreadLocal<DsKey>() {
        @Override
        protected DsKey initialValue() {
            return DsKey.DATASOURCE;
        }
    };
    @Autowired
    private DynamicDataSourceBuilder dynamicDataSourceBuilder;

    // 维护数据源 key(Lookup key)
    private static Set<String> dsKeySet = new HashSet<>();

    public static DsKey getDataSourceKey() {
        return dataSourceKey.get();
    }
    public static void setDataSourceKey(DsKey key) {
        dataSourceKey.set(key);
    }

    static int addDsKey(String key) {
        dsKeySet.add(key);
        return dsKeySet.size();
    }
    public static void clearDataSourceType() {
        dataSourceKey.remove();
    }
    public static boolean contains(String key) {
        return dsKeySet.contains(key);
    }
    public static boolean contains(DsKey key) {
        return dsKeySet.contains(key.getCode());
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return dataSourceKey.get();
    }

    @Override
    public void afterPropertiesSet() {

        // 所有数据源,包括默认数据源
        Map<String, DataSource> customDataSources = dynamicDataSourceBuilder.getTargetDataSources();

        // Lookup key
        customDataSources.forEach((key, da) -> addDsKey(key));

        // DataSource
        DataSource defaultDataSource = dynamicDataSourceBuilder.getDefaultDataSource();
        setDefaultTargetDataSource(defaultDataSource);
        setTargetDataSources(new HashMap<>(customDataSources));

        super.afterPropertiesSet();
    }
}

AOP 的方式进行动态切换

定义注解供 AOP 进行拦截,以切换数据源:


image.png

在使用了 DataSource 注解的地方进行数据源切换,方法调用结束时恢复默认数据源:

image.png
在具体业务中如果需要更细粒度的控制数据源,也可直接调用 DynamicDataSource.setDataSourceKey 方法设置数据源,同时在结束操作时需要调用 DynamicDataSource.clearDataSourceType 方法恢复默认数据源。

使用示例

public class TestService {


    @DataSource(dsKey = DsKey.DB1)
    public void test() {
        //
    }

    @DataSource(dsKey = DsKey.DB1)
    public void test1() {
        DynamicDataSource.setDataSourceKey(DsKey.DATASOURCE);
        // do somthing
        DynamicDataSource.setDataSourceKey(DsKey.DB1);
    }


}

代码已上传 GitHub,可以在 这里 找到

上一篇 下一篇

猜你喜欢

热点阅读