mybatis 动态数据源核心--AbstractRoutingDataSource
1 public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean { 2 @Nullable 3 private Map<Object, Object> targetDataSources; 4 @Nullable 5 private Object defaultTargetDataSource; 6 private boolean lenientFallback = true; 7 private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup(); 8 @Nullable 9 private Map<Object, DataSource> resolvedDataSources; 10 @Nullable 11 private DataSource resolvedDefaultDataSource; 12 13 public AbstractRoutingDataSource() { 14 } 15 16 //设置当前所支持的数据源列表 是key-datasource列表形式哦 通过切换key就切换了数据源 17 public void setTargetDataSources(Map<Object, Object> targetDataSources) { 18 this.targetDataSources = targetDataSources; 19 } 20 21 //设置默认的数据源 22 public void setDefaultTargetDataSource(Object defaultTargetDataSource) { 23 this.defaultTargetDataSource = defaultTargetDataSource; 24 } 25 26 public void setLenientFallback(boolean lenientFallback) { 27 this.lenientFallback = lenientFallback; 28 } 29 30 public void setDataSourceLookup(@Nullable DataSourceLookup dataSourceLookup) { 31 this.dataSourceLookup = (DataSourceLookup)(dataSourceLookup != null ? dataSourceLookup : new JndiDataSourceLookup()); 32 } 33 34 public void afterPropertiesSet() { 35 if (this.targetDataSources == null) { 36 throw new IllegalArgumentException("Property 'targetDataSources' is required"); 37 } else { 38 this.resolvedDataSources = CollectionUtils.newHashMap(this.targetDataSources.size());
39 this.targetDataSources.forEach((key, value) -> {//解析datasource 40 Object lookupKey = this.resolveSpecifiedLookupKey(key); 41 DataSource dataSource = this.resolveSpecifiedDataSource(value); 42 this.resolvedDataSources.put(lookupKey, dataSource); 43 }); 44 if (this.defaultTargetDataSource != null) { 45 this.resolvedDefaultDataSource = this.resolveSpecifiedDataSource(this.defaultTargetDataSource); 46 } 47 48 } 49 } 50 51 protected Object resolveSpecifiedLookupKey(Object lookupKey) { 52 return lookupKey; 53 } 54 55 protected DataSource resolveSpecifiedDataSource(Object dataSource) throws IllegalArgumentException {
//datasource 可以是DataSource实现类 也可以是string参数 56 if (dataSource instanceof DataSource) { 57 return (DataSource)dataSource; 58 } else if (dataSource instanceof String) { 59 return this.dataSourceLookup.getDataSource((String)dataSource); 60 } else { 61 throw new IllegalArgumentException("Illegal data source value - only [javax.sql.DataSource] and String supported: " + dataSource); 62 } 63 } 64 65 public Map<Object, DataSource> getResolvedDataSources() { 66 Assert.state(this.resolvedDataSources != null, "DataSources not resolved yet - call afterPropertiesSet"); 67 return Collections.unmodifiableMap(this.resolvedDataSources); 68 } 69 70 @Nullable 71 public DataSource getResolvedDefaultDataSource() { 72 return this.resolvedDefaultDataSource; 73 } 74 75 public Connection getConnection() throws SQLException { 76 return this.determineTargetDataSource().getConnection(); 77 } 78 79 public Connection getConnection(String username, String password) throws SQLException { 80 return this.determineTargetDataSource().getConnection(username, password); 81 } 82 83 public <T> T unwrap(Class<T> iface) throws SQLException { 84 return iface.isInstance(this) ? this : this.determineTargetDataSource().unwrap(iface); 85 } 86 87 public boolean isWrapperFor(Class<?> iface) throws SQLException { 88 return iface.isInstance(this) || this.determineTargetDataSource().isWrapperFor(iface); 89 } 90 91 protected DataSource determineTargetDataSource() { 92 Assert.notNull(this.resolvedDataSources, "DataSource router not initialized"); 93 //动态获取当前数据源 key , determineCurrentLookupKey 是关键,我们可以自己实现的切换逻辑 94 Object lookupKey = this.determineCurrentLookupKey(); 95 DataSource dataSource = (DataSource)this.resolvedDataSources.get(lookupKey); 96 if (dataSource == null && (this.lenientFallback || lookupKey == null)) { 97 dataSource = this.resolvedDefaultDataSource; 98 } 99 100 if (dataSource == null) { 101 throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]"); 102 } else { 103 return dataSource; 104 } 105 } 106 107 //这是抽象方法,需要自己实现哦 108 @Nullable 109 protected abstract Object determineCurrentLookupKey(); 110 }