java事务动态切换数据源,spring动态切换数据源(一)

1 spring动态切换连接池需要类AbstractRoutingDataSource的源码2 /*

3 * Copyright 2002-2017 the original author or authors.4 *5 * Licensed under the Apache License, Version 2.0 (the "License");6 * you may not use this file except in compliance with the License.7 * You may obtain a copy of the License at8 *9 *http://www.apache.org/licenses/LICENSE-2.0

10 *11 * Unless required by applicable law or agreed to in writing, software12 * distributed under the License is distributed on an "AS IS" BASIS,13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.14 * See the License for the specific language governing permissions and15 * limitations under the License.16 */

17

18 packageorg.springframework.jdbc.datasource.lookup;19

20 importjava.sql.Connection;21 importjava.sql.SQLException;22 importjava.util.HashMap;23 importjava.util.Map;24 importjavax.sql.DataSource;25

26 importorg.springframework.beans.factory.InitializingBean;27 importorg.springframework.jdbc.datasource.AbstractDataSource;28 importorg.springframework.lang.Nullable;29 importorg.springframework.util.Assert;30

31 /**

32 * Abstract {@linkjavax.sql.DataSource} implementation that routes {@link#getConnection()}33 * calls to one of various target DataSources based on a lookup key. The latter is usually34 * (but not necessarily) determined through some thread-bound transaction context.35 *36 *@authorJuergen Hoeller37 *@since2.0.138 *@see#setTargetDataSources39 *@see#setDefaultTargetDataSource40 *@see#determineCurrentLookupKey()41 */

42 public abstract class AbstractRoutingDataSource extends AbstractDataSource implementsInitializingBean {43

44 @Nullable45 private MaptargetDataSources;46

47 @Nullable48 privateObject defaultTargetDataSource;49

50 private boolean lenientFallback = true;51

52 private DataSourceLookup dataSourceLookup = newJndiDataSourceLookup();53

54 @Nullable55 private MapresolvedDataSources;56

57 @Nullable58 privateDataSource resolvedDefaultDataSource;59

60

61 / * *

62 *指定目标数据源的映射,查找键为键。63 *映射的值可以是对应的{@link javax.sql.DataSource}64 实例或数据源名称字符串(通过{@link setDataSourceLookup DataSourceLookup}解析)。65 *

密钥可以是任意类型;该类只实现泛型查找过程。66 具体的键表示将由{67 @link # resolvespeciedlookupkey (Object)}和{@link #行列式urrentlookupkey()}处理。68 * /

69 public void setTargetDataSources(MaptargetDataSources) {70 this.targetDataSources =targetDataSources;71 }72

73

74

75

76 / * *

77 *指定默认的目标数据源(如果有的话)。78 *

映射值可以是对应的79 {@link javax.sql.DataSource}80 实例或数据源名称字符串81 (通过{@link #setDataSourceLookup DataSourceLookup}解析)。82 *

如果key {@link #setTargetDataSources targetDataSources}83 没有匹配{@link #决定ecurrentlookupkey()}当前查找键,84 则此数据源将被用作目标。85 * /

86

87 public voidsetDefaultTargetDataSource(Object defaultTargetDataSource) {88 this.defaultTargetDataSource =defaultTargetDataSource;89 }90

91 / * *

92 *指定是否对默认数据源应用宽松的回退93 *如果无法为当前查找键找到特定的数据源。94 *

默认为“true”,接受在目标数据源映射中没有对应条目的查找键——在这种情况下,简单地返回到默认数据源。95 *

将此标志切换为“false”,如果您希望回退仅在查找键为{@code null}时应用。96 没有数据源项的查找键将导致IllegalStateException。97 *@see # setTargetDataSources98 *@see # setDefaultTargetDataSource99 *@see # determineCurrentLookupKey ()100 * /

101 public void setLenientFallback(booleanlenientFallback) {102 this.lenientFallback =lenientFallback;103 }104

105 / * *

106 *设置DataSourceLookup实现来解析数据源107 {@link #setTargetDataSources targetDataSources}映射中的名称字符串。108 *

默认是{@link JndiDataSourceLookup},允许JNDI名称109 *直接指定的应用服务器数据源。110 * /

111 public voidsetDataSourceLookup(@Nullable DataSourceLookup dataSourceLookup) {112 this.dataSourceLookup = (dataSourceLookup != null ? dataSourceLookup : newJndiDataSourceLookup());113 }114

115

116 @Override117 public voidafterPropertiesSet() {118 if (this.targetDataSources == null) {119 throw new IllegalArgumentException("Property 'targetDataSources' is required");120 }121 this.resolvedDataSources = new HashMap<>(this.targetDataSources.size());122 this.targetDataSources.forEach((key, value) ->{123 Object lookupKey =resolveSpecifiedLookupKey(key);124 DataSource dataSource =resolveSpecifiedDataSource(value);125 this.resolvedDataSources.put(lookupKey, dataSource);126 });127 if (this.defaultTargetDataSource != null) {128 this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);129 }130 }131

132 / * *

133 *将给定的查找键对象134 *(如{@link #setTargetDataSources targetDataSources}映射中指定的)解析为实际的查找键,135 *用于与{@link #决定ecurrentlookupkey()当前查找键}匹配。136 *

默认实现只是简单地返回给定的键值。137 *@param lookupKey用户指定的查找键对象138 *@根据需要返回查找键以进行匹配139 * /

140 protectedObject resolveSpecifiedLookupKey(Object lookupKey) {141 returnlookupKey;142 }143

144

145 / * *

146 *将指定的数据源对象解析为数据源实例。147 *

默认实现处理数据源实例和数据源名称(通过{@link #setDataSourceLookup DataSourceLookup}解析)。148 {@link #setTargetDataSources targetDataSources}映射中指定的数据源值对象149 * @返回已解析的数据源(绝不是{@code null})150 *@抛出不支持的值类型的IllegalArgumentException151 * /

152

153 protected DataSource resolveSpecifiedDataSource(Object dataSource) throwsIllegalArgumentException {154 if (dataSource instanceofDataSource) {155 return(DataSource) dataSource;156 }157 else if (dataSource instanceofString) {158 return this.dataSourceLookup.getDataSource((String) dataSource);159 }160 else{161 throw newIllegalArgumentException(162 "Illegal data source value - only [javax.sql.DataSource] and String supported: " +dataSource);163 }164 }165

166

167 @Override168 public Connection getConnection() throwsSQLException {169 returndetermineTargetDataSource().getConnection();170 }171

172 @Override173 public Connection getConnection(String username, String password) throwsSQLException {174 returndetermineTargetDataSource().getConnection(username, password);175 }176

177 @Override178 @SuppressWarnings("unchecked")179 public T unwrap(Class iface) throwsSQLException {180 if (iface.isInstance(this)) {181 return (T) this;182 }183 returndetermineTargetDataSource().unwrap(iface);184 }185

186 @Override187 public boolean isWrapperFor(Class> iface) throwsSQLException {188 return (iface.isInstance(this) ||determineTargetDataSource().isWrapperFor(iface));189 }190

191

192 /**

193 *检索当前目标数据源。决定了194 * {@link# definecurrentlookupkey()当前查找键},在{@link#setTargetDataSources targetDataSources}映射中执行查找,返回指定的195 * {@link#setDefaultTargetDataSource默认目标数据源}如果需要。196 *@see# determineCurrentLookupKey ()197

198 通多debug会发现DataSource dataSource = this.resolvedDataSources.get(lookupKey);非常关键。获取数据源类似key的标识199

200 */

201

202 protectedDataSource determineTargetDataSource() {203 Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");204 Object lookupKey =determineCurrentLookupKey();205 DataSource dataSource = this.resolvedDataSources.get(lookupKey);206 if (dataSource == null && (this.lenientFallback || lookupKey == null)) {207 dataSource = this.resolvedDefaultDataSource;//没有数据源设置为默认的数据源

208 }209 if (dataSource == null) {//没切换数据源并且没有设置默认数据源,此处抛出异常

210 throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");211 }212 return dataSource;//返回数据源对象

213 }214

215 /*

216 * 确定当前查找键。这通常是217 *用于检查线程绑定的事务上下文。218 *

允许任意键。返回的密钥需要方法解析后匹配存储的查找键类型219 * {@link # resolvespeciedlookupkey}方法。220 */

221 @Nullable222 protected abstract Object determineCurrentLookupKey();//抽像方法,需要重写然后在protected DataSource determineTargetDataSource() 中调用

223

224 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值