Spring多数据源配置系列(二)——AbstractRoutingDataSource详解

来源:互联网 发布:万方数据库账号 编辑:程序博客网 时间:2024/05/16 23:35

我们来查看AbstractRoutingDataSource源码,来更好的理解多数据源配置。

首先查看该类的属性,根据名称我们能看出他们的作用。

private Map<Object, Object> targetDataSources;private Object defaultTargetDataSource;private boolean lenientFallback = true;private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();private Map<Object, DataSource> resolvedDataSources;private DataSource resolvedDefaultDataSource;

targetDataSources是目标数据源集合

defaultTargetDataSource是默认数据源

resolvedDataSources是解析后的数据源集合

resolvedDefaultDataSource是解析后的默认数据源

对数据源赋值的代码如下

public void setTargetDataSources(Map<Object, Object> targetDataSources) {    this.targetDataSources = targetDataSources;}public void setDefaultTargetDataSource(Object defaultTargetDataSource) {    this.defaultTargetDataSource = defaultTargetDataSource;}
因为方法是set开头,我们便能把这两个方法配置在spring中,继续向下看。
public void afterPropertiesSet() {    if (this.targetDataSources == null) {        throw new IllegalArgumentException("Property 'targetDataSources' is required");    } else {        this.resolvedDataSources = new HashMap(this.targetDataSources.size());        Iterator var1 = this.targetDataSources.entrySet().iterator();        while(var1.hasNext()) {            Entry<Object, Object> entry = (Entry)var1.next();            Object lookupKey = this.resolveSpecifiedLookupKey(entry.getKey());            DataSource dataSource = this.resolveSpecifiedDataSource(entry.getValue());            this.resolvedDataSources.put(lookupKey, dataSource);        }        if (this.defaultTargetDataSource != null) {            this.resolvedDefaultDataSource = this.resolveSpecifiedDataSource(this.defaultTargetDataSource);        }    }}

这个afterPropertiesSet方法是遍历我们的targetDataSources数据源集合,并添加resolvedDataSources的map数据,map的key和value是根据resolveSpecifiedLookupKey方法和resolveSpecifiedDataSource方法得到。接着找到resolveSpecifiedLookupKey和resolveSpecifiedDataSource。

protected Object resolveSpecifiedLookupKey(Object lookupKey) {    return lookupKey;}protected DataSource resolveSpecifiedDataSource(Object dataSource) throws IllegalArgumentException {    if (dataSource instanceof DataSource) {        return (DataSource)dataSource;    } else if (dataSource instanceof String) {        return this.dataSourceLookup.getDataSource((String)dataSource);    } else {        throw new IllegalArgumentException("Illegal data source value - only [javax.sql.DataSource] and String supported: " + dataSource);    }}

resolveSpecifiedLookupKey方法返回的实际就是targetDataSources的key,而resolveSpecifiedDataSource返回的是targetDataSources的value转成的DataSource。afterPropertiesSet方法的作用实际就是将原targetDataSources转成resolvedDataSources。

继续向下看,我们能看到数据库的连接方法。

public Connection getConnection() throws SQLException {    return this.determineTargetDataSource().getConnection();}public Connection getConnection(String username, String password) throws SQLException {    return this.determineTargetDataSource().getConnection(username, password);}

我们接着去看determineTargeDataSource方法,估计这个方法是返回指定数据源的。

protected DataSource determineTargetDataSource() {    Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");    Object lookupKey = this.determineCurrentLookupKey();    DataSource 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 + "]");    } else {        return dataSource;    }}

果然,这个方法是返回数据源的,我们来仔细读这个方法,从第3行开始”Object lookupKey = this.determineCurrentLookupKey();”,这个determineCurrentLookupKey返回了一个key,第四句是根据这个key去resolvedDataSources中拿到对应DataSource,接下来的代码是DataSource不存在便返回默认的数据源。determineCurrentLookupKey方法就是返回key的逻辑处理部分,联系spring中的配置,它返回的就是”cms”、”epg”中的一个。

<bean id="dynamicDataSource" class="com.lc.rout.DynamicDataSource">    <property name="targetDataSources">        <map>            <entry key="cms" value-ref="cmsDataSource"/>            <entry key="epg" value-ref="epgDataSource"/>        </map>    </property></bean>

我们在来看determineCurrentLookupKey方法。它是一个抽象方法,需要我们自己去写。

protected abstract Object determineCurrentLookupKey();

所以,我们需要实现这个抽象方法,返回一个指定数据源对应的key。

阅读全文
0 0
原创粉丝点击