Spring多数据源抽象类

在稍微比较庞大的系统中,很有可能涉及分库等多数据源的情况。这时候可能选用一些流程的框架,比如:Sharding-JDBC。但是相比Shardding-JDBC的复杂度,也许实现Spring的抽象类:AbstractRoutingDataSource 更合适和轻便。
该抽象类的定义如下:

/**
 * Abstract {@link javax.sql.DataSource} implementation that routes {@link #getConnection()}
 * calls to one of various target DataSources based on a lookup key. The latter is usually
 * (but not necessarily) determined through some thread-bound transaction context.
 *
 * @author Juergen Hoeller
 * @since 2.0.1
 * @see #setTargetDataSources
 * @see #setDefaultTargetDataSource
 * @see #determineCurrentLookupKey()
 */
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {

1:新建立类继承抽象类 AbstractRoutingDataSource。一般情况下只需要实现抽象接口:determineCurrentLookupKey。该方法是获取数据源的KEY,如果该接口返回的类型是自定义对象,切记要重写 equal() 和 hasCode() 方法。

2:使用的时候,一般只需要给2个属性赋值。 一是调用 setTargetDataSources() 方法设置多个数据源。二是调用 setDefaultTargetDataSource() 设置默认的数据源(当使用 determineCurrentLookupKey() 方法得到的key找不到数据源时,将使用默认数据源)

3:AbstractRoutingDataSource 抽象类实例化后,会调用 afterPropertiesSet() 方法。该方法就是解析设置的数据源,代码如下:

public void afterPropertiesSet() {
        if (this.targetDataSources == null) {
            throw new IllegalArgumentException("Property 'targetDataSources' is required");
        }
        this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size());
        for (Map.Entry<Object, Object> entry : this.targetDataSources.entrySet()) {
            Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());
            DataSource dataSource = resolveSpecifiedDataSource(entry.getValue());
            this.resolvedDataSources.put(lookupKey, dataSource);
        }
        if (this.defaultTargetDataSource != null) {
            this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);
        }
    }

4:该类继承了DataSource 接口。重写了 getConnection 接口。在getConnection 接口中会根据得到的KEY,去指定的数据源获取连接。代码如下:

    @Override
    public Connection getConnection() throws SQLException {
        return determineTargetDataSource().getConnection();
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return determineTargetDataSource().getConnection(username, password);
    }
protected DataSource determineTargetDataSource() {
        Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
        Object lookupKey = determineCurrentLookupKey();
        DataSource dataSource = this.resolvedDataSources.get(lookupKey);
        if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
            dataSource = this.resolvedDefaultDataSource;
        }
        if (dataSource == null) {
            throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
        }
        return dataSource;
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。