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 }