mybatis 动态数据源核心--AbstractRoutingDataSource

发布时间 2023-06-29 11:48:03作者: dint
  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) -> {
 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 {
 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 }