From 193ccd3855db5182e3820530861d0a2eaadf55b3 Mon Sep 17 00:00:00 2001 From: chxlay Date: Sat, 7 Dec 2024 16:41:11 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86@UseDataSource?= =?UTF-8?q?=E5=8F=96=E5=80=BC=E5=8A=A8=E6=80=81=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E6=94=AF=E6=8C=81=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1:DataSourceProcessor 为处理器接口 2:DelegatingDataSourceProcessor 为DataSourceProcessor的委托类,目的增强扩大 DataSourceProcessor类或对象的结构 3:ParamIndexDataSourceProcessor 简单参数所以读取的支持处理器 4:SpelExpressionDataSourceProcessor 支持SPEL 表达式的处理器类 --- .../core/datasource/DataSourceKey.java | 10 ++ .../core/datasource/DataSourceManager.java | 19 ++++ .../processor/DataSourceProcessor.java | 25 +++++ .../DelegatingDataSourceProcessor.java | 54 +++++++++ .../ParamIndexDataSourceProcessor.java | 58 ++++++++++ .../datasource/processor/package-info.java | 20 ++++ .../core/mybatis/binding/FlexMapperProxy.java | 8 +- .../SpelExpressionDataSourceProcessor.java | 106 ++++++++++++++++++ .../datasource/processor/package-info.java | 20 ++++ 9 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/ParamIndexDataSourceProcessor.java create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/package-info.java create mode 100644 mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/processor/SpelExpressionDataSourceProcessor.java create mode 100644 mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/processor/package-info.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java index a2c8d43c..a7f43231 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java @@ -78,6 +78,12 @@ public class DataSourceKey { lookup = threadLocal; } + public static String processDataSourceKey(String dataSourceKey, Object mapper, Method method, Object[] arguments) { + String dsKey = DataSourceManager.processDataSourceKey(dataSourceKey, mapper, method, arguments); + return dsKey != null ? dsKey : dataSourceKey; + } + + public static String getShardingDsKey(String dataSource, Object mapper, Method method, Object[] args) { String shardingDsKey = DataSourceManager.getShardingDsKey(dataSource, mapper, method, args); return shardingDsKey != null ? shardingDsKey : dataSource; @@ -89,18 +95,22 @@ public class DataSourceKey { public static String getByManual() { throw new UnsupportedOperationException("使用 DataSource.get() 代替。"); } + @Deprecated public static String getByAnnotation() { throw new UnsupportedOperationException("使用 DataSource.get() 代替。"); } + @Deprecated public static void useWithAnnotation(String dataSourceKey) { throw new UnsupportedOperationException("使用 DataSource.use(String) 代替。"); } + @Deprecated public static void setAnnotationKeyThreadLocal(ThreadLocal annotationKeyThreadLocal) { throw new UnsupportedOperationException("使用 DataSource.setThreadLocal(ThreadLocal>) 代替。"); } + @Deprecated public static void setManualKeyThreadLocal(ThreadLocal manualKeyThreadLocal) { throw new UnsupportedOperationException("使用 DataSource.setThreadLocal(ThreadLocal>) 代替。"); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java index e3cfe067..ce68caba 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java @@ -15,6 +15,7 @@ */ package com.mybatisflex.core.datasource; +import com.mybatisflex.core.datasource.processor.DataSourceProcessor; import com.mybatisflex.core.exception.FlexExceptions; import com.mybatisflex.core.util.ClassUtil; import org.apache.ibatis.logging.LogFactory; @@ -37,6 +38,19 @@ public class DataSourceManager { DataSourceManager.decipher = decipher; } + /** + * 动态数据源key取值处理 + */ + private static DataSourceProcessor dataSourceProcessor; + + public static DataSourceProcessor getDataSourceProcessor() { + return dataSourceProcessor; + } + + public static void setDataSourceProcessor(DataSourceProcessor dataSourceProcessor) { + DataSourceManager.dataSourceProcessor = dataSourceProcessor; + } + private static DataSourceShardingStrategy dataSourceShardingStrategy; public static DataSourceShardingStrategy getDataSourceShardingStrategy() { @@ -95,6 +109,11 @@ public class DataSourceManager { return null; } + static String processDataSourceKey(String dataSourceKey, Object mapper, Method method, Object[] arguments) { + // 如果没有配置 DataSourceProcessor 实例,则不做处理,返回原始值 + return dataSourceProcessor == null ? dataSourceKey : dataSourceProcessor.process(dataSourceKey, mapper, method, arguments); + } + static String getShardingDsKey(String dataSource, Object mapper, Method method, Object[] args) { return dataSourceShardingStrategy != null ? dataSourceShardingStrategy.doSharding(dataSource, mapper, method, args) : null; diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java new file mode 100644 index 00000000..918885cd --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java @@ -0,0 +1,25 @@ +package com.mybatisflex.core.datasource.processor; + +import java.lang.reflect.Method; + +/** + * 动态数据源 @UseDataSource key 解析处理器,使用时推荐注入 DelegatingDataSourceProcessor{@link DelegatingDataSourceProcessor} 类 + * 对动态数据源注解@UseDataSource 增强处理{@link com.mybatisflex.annotation.UseDataSource} + * + * @author Alay + * @since 2024-12-07 15:34 + */ +public interface DataSourceProcessor { + + /** + * 数据源key解析扩展 + * + * @param dataSourceKey 注解UseDataSource的value 值,调用process时不会为null,可能会空字符串 + * @param mapper Mapper对象(代理对象) + * @param method Mapper当前执行的方法函数 + * @param arguments Mapper当前执行的函数参数 + * @return 数据源名称(可能为null 为 null 时表示不符合当前处理器的处理,传递到下一个处理器进行处理) + */ + String process(String dataSourceKey, Object mapper, Method method, Object[] arguments); + +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java new file mode 100644 index 00000000..9f0c9db8 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java @@ -0,0 +1,54 @@ +package com.mybatisflex.core.datasource.processor; + +import com.mybatisflex.core.exception.FlexAssert; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * DataSourceProcessor 委托扩展类,对 DataSourceProcessor 结构进行扩大和增强 + * + * @author Alay + * @since 2024-12-07 15:38 + */ +public class DelegatingDataSourceProcessor implements DataSourceProcessor { + + private final List delegates; + + + private DelegatingDataSourceProcessor(List delegates) { + this.delegates = delegates; + } + + /** + * @param processors 使用时请注意 DataSourceProcessor 的顺序 + */ + public static DelegatingDataSourceProcessor with(DataSourceProcessor... processors) { + FlexAssert.notEmpty(processors, "datasource processors"); + List dataSourceProcessors = new ArrayList<>(Arrays.asList(processors)); + return new DelegatingDataSourceProcessor(dataSourceProcessors); + } + + /** + * @param processors 使用时请注意 DataSourceProcessor 的顺序 + */ + public static DelegatingDataSourceProcessor with(List processors) { + FlexAssert.notEmpty(processors, "datasource processors"); + return new DelegatingDataSourceProcessor(processors); + } + + + @Override + public String process(String dataSourceKey, Object mapper, Method method, Object[] arguments) { + for (DataSourceProcessor delegate : delegates) { + // 使用时请注意 DataSourceProcessor 的顺序,一旦匹配到处理器将进行中断处理并返回处理结果 + String returnKey = delegate.process(dataSourceKey, mapper, method, arguments); + if (null != returnKey) return returnKey; + } + // 无可用的处理器策略,返回原始值 + return dataSourceKey; + } + +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/ParamIndexDataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/ParamIndexDataSourceProcessor.java new file mode 100644 index 00000000..5dbfaec5 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/ParamIndexDataSourceProcessor.java @@ -0,0 +1,58 @@ +package com.mybatisflex.core.datasource.processor; + +import com.mybatisflex.processor.util.StrUtil; + +import java.lang.reflect.Method; + +/** + * 参数索引中取出数据源名称(针对简单类型参数快速解析读取) + * + * @author Alay + * @since 2024-12-07 15:43 + */ +public class ParamIndexDataSourceProcessor implements DataSourceProcessor { + private static final String NULL_STR = "null"; + private static final String DYNAMIC_PREFIX = "#"; + private static final String INDEX_FIRST = "#first"; + private static final String INDEX_LAST = "#last"; + private static final String PARAM_INDEX = "#index"; + + /** + * 若不符合处理逻辑将返回 null 值 + */ + @Override + public String process(String dataSourceKey, Object mapper, Method method, Object[] arguments) { + if (StrUtil.isBlank(dataSourceKey)) return null; + if (!dataSourceKey.startsWith(DYNAMIC_PREFIX)) return null; + // 无效的参数 + if (arguments.length == 0) return null; + + Integer index = null; + if (INDEX_FIRST.equals(dataSourceKey)) index = 0; + if (INDEX_LAST.equals(dataSourceKey)) index = arguments.length - 1; + if (dataSourceKey.startsWith(PARAM_INDEX)) index = parseIndex(dataSourceKey); + + // 没有符合约定的格式输入,则会返回 null + if (null == index) return null; + // 参数输入不合法(索引参数大于参数索引数) + if (index >= arguments.length) return null; + + // 参数中按照索引取出数值 + String value = String.valueOf(arguments[index]); + if (StrUtil.isBlank(value) || NULL_STR.equals(value)) return null; + + return value; + } + + private static Integer parseIndex(String dsKey) { + // 参数索引 + String indexStr = dsKey.substring(PARAM_INDEX.length()); + if (indexStr.isEmpty()) return null; + try { + return Integer.parseInt(indexStr); + } catch (NumberFormatException ex) { + return null; + } + } + +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/package-info.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/package-info.java new file mode 100644 index 00000000..92b50d19 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 动态数据源注解@UseDataSource 的扩展 + */ +package com.mybatisflex.core.datasource.processor; diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java index 01090e53..d52f7ec8 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java @@ -26,6 +26,7 @@ import com.mybatisflex.core.row.RowMapper; import com.mybatisflex.core.table.TableInfo; import com.mybatisflex.core.table.TableInfoFactory; import com.mybatisflex.core.util.StringUtil; +import com.mybatisflex.processor.util.StrUtil; import org.apache.ibatis.reflection.ExceptionUtil; import org.apache.ibatis.session.SqlSession; @@ -61,7 +62,12 @@ public class FlexMapperProxy extends MybatisMapperProxy { finalDsKey = getMethodDsKey(method, proxy); } - //通过自定义分配策略去获取最终的数据源 + // 对数据源取值进行动态取值处理(#) + if (!StrUtil.isBlank(finalDsKey)) { + finalDsKey = DataSourceKey.processDataSourceKey(finalDsKey, proxy, method, args); + } + + // 通过自定义分配策略去获取最终的数据源 finalDsKey = DataSourceKey.getShardingDsKey(finalDsKey, proxy, method, args); if (StringUtil.hasText(finalDsKey) && !finalDsKey.equals(userDsKey)) { diff --git a/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/processor/SpelExpressionDataSourceProcessor.java b/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/processor/SpelExpressionDataSourceProcessor.java new file mode 100644 index 00000000..7052c6dd --- /dev/null +++ b/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/processor/SpelExpressionDataSourceProcessor.java @@ -0,0 +1,106 @@ +package com.mybatisflex.spring.datasource.processor; + +import com.mybatisflex.core.datasource.processor.DataSourceProcessor; +import com.mybatisflex.processor.util.StrUtil; +import org.springframework.context.expression.MethodBasedEvaluationContext; +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.expression.BeanResolver; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.ParserContext; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import java.lang.reflect.Method; + +/** + * SpEL表达式支持处理器 + * + * @author Alay + * @since 2024-12-07 15:48 + */ +public class SpelExpressionDataSourceProcessor implements DataSourceProcessor { + /** + * 动态表达式前缀 + */ + private static final String DYNAMIC_PREFIX = "#"; + /** + * 参数发现器 + */ + private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); + /** + * Express语法解析器 + */ + private static final ExpressionParser PARSER = new SpelExpressionParser(); + + private BeanResolver beanResolver; + /** + * 解析上下文的模板 对于默认不设置的情况下,从参数中取值的方式 #param1 + * 设置指定模板 ParserContext. TEMPLATE_EXPRESSION{@link ParserContext#TEMPLATE_EXPRESSION} 后的取值方式: #{#param1} + */ + private ParserContext parserContext = new ParserContext() { + + @Override + public boolean isTemplate() { + return false; + } + + @Override + public String getExpressionPrefix() { + return null; + } + + @Override + public String getExpressionSuffix() { + return null; + } + }; + + + @Override + public String process(String dataSourceKey, Object mapper, Method method, Object[] arguments) { + if (StrUtil.isBlank(dataSourceKey)) return null; + if (!dataSourceKey.startsWith(DYNAMIC_PREFIX)) return null; + if (arguments.length == 0) return null; + + RootObject rootObject = new RootObject(method, arguments, mapper); + StandardEvaluationContext context = new MethodBasedEvaluationContext(rootObject, method, arguments, NAME_DISCOVERER); + context.setBeanResolver(beanResolver); + final Object value = PARSER.parseExpression(dataSourceKey, parserContext).getValue(context); + return value == null ? null : value.toString(); + } + + + public void setBeanResolver(BeanResolver beanResolver) { + this.beanResolver = beanResolver; + } + + public void setParserContext(ParserContext parserContext) { + this.parserContext = parserContext; + } + + public static class RootObject { + private final Method method; + private final Object[] args; + private final Object target; + + public RootObject(Method method, Object[] args, Object target) { + this.method = method; + this.args = args; + this.target = target; + } + + public Method getMethod() { + return method; + } + + public Object[] getArgs() { + return args; + } + + public Object getTarget() { + return target; + } + } + +} diff --git a/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/processor/package-info.java b/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/processor/package-info.java new file mode 100644 index 00000000..9f7f60c0 --- /dev/null +++ b/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/processor/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 动态数据源注解@UseDataSource 的扩展 + */ +package com.mybatisflex.spring.datasource.processor; From 8a14307fbafee46cfc0673ffcd8127d04fee9784 Mon Sep 17 00:00:00 2001 From: chxlay Date: Sat, 7 Dec 2024 17:00:50 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86@UseDataSource?= =?UTF-8?q?=E5=8F=96=E5=80=BC=E5=8A=A8=E6=80=81=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E6=94=AF=E6=8C=81=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1:DataSourceProcessor 为处理器接口 2:DelegatingDataSourceProcessor 为DataSourceProcessor的委托类,目的增强扩大 DataSourceProcessor类或对象的结构 3:ParamIndexDataSourceProcessor 简单参数所以读取的支持处理器 4:SpelExpressionDataSourceProcessor 支持SPEL 表达式的处理器类 --- .../core/datasource/processor/DataSourceProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java index 918885cd..261d6a34 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java @@ -18,7 +18,7 @@ public interface DataSourceProcessor { * @param mapper Mapper对象(代理对象) * @param method Mapper当前执行的方法函数 * @param arguments Mapper当前执行的函数参数 - * @return 数据源名称(可能为null 为 null 时表示不符合当前处理器的处理,传递到下一个处理器进行处理) + * @return 数据源名称(可能为null 为 null 时表示不符合当前处理器的处理) */ String process(String dataSourceKey, Object mapper, Method method, Object[] arguments); From 3ef1ed59ad0c5badba22868cf770ac8630044863 Mon Sep 17 00:00:00 2001 From: chxlay Date: Sat, 7 Dec 2024 17:04:58 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86@UseDataSource?= =?UTF-8?q?=E5=8F=96=E5=80=BC=E5=8A=A8=E6=80=81=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E6=94=AF=E6=8C=81=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1:DataSourceProcessor 为处理器接口 2:DelegatingDataSourceProcessor 为DataSourceProcessor的委托类,目的增强扩大 DataSourceProcessor类或对象的结构 3:ParamIndexDataSourceProcessor 简单参数所以读取的支持处理器 4:SpelExpressionDataSourceProcessor 支持SPEL 表达式的处理器类 --- .../processor/DelegatingDataSourceProcessor.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java index 9f0c9db8..e15f1b92 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java @@ -9,12 +9,16 @@ import java.util.List; /** * DataSourceProcessor 委托扩展类,对 DataSourceProcessor 结构进行扩大和增强 + * 如果多个实例化,建议通过 DelegatingDataSourceProcessor.with(多个解析处理器实例) 方式进行实例化。 + * 需要注意的是委托解析处理器之间有先后顺序,一点排列前面的解析处理器正常处理后,将直接返回处理值,不再往下传递处理 * * @author Alay * @since 2024-12-07 15:38 */ public class DelegatingDataSourceProcessor implements DataSourceProcessor { - + /** + * 多个处理器委托集合(使用时请注意 DataSourceProcessor 的顺序) + */ private final List delegates; @@ -43,7 +47,7 @@ public class DelegatingDataSourceProcessor implements DataSourceProcessor { @Override public String process(String dataSourceKey, Object mapper, Method method, Object[] arguments) { for (DataSourceProcessor delegate : delegates) { - // 使用时请注意 DataSourceProcessor 的顺序,一旦匹配到处理器将进行中断处理并返回处理结果 + // 使用时请注意 DataSourceProcessor 的顺序,一旦匹配到处理器将进行终止处理链,并返回当前处理结果 String returnKey = delegate.process(dataSourceKey, mapper, method, arguments); if (null != returnKey) return returnKey; } From 305723961e992e6ff6697e66f195be3b9756cb75 Mon Sep 17 00:00:00 2001 From: chxlay Date: Sat, 7 Dec 2024 17:08:48 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/datasource/processor/DataSourceProcessor.java | 2 +- .../com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java index 261d6a34..4533f6b5 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java @@ -3,7 +3,7 @@ package com.mybatisflex.core.datasource.processor; import java.lang.reflect.Method; /** - * 动态数据源 @UseDataSource key 解析处理器,使用时推荐注入 DelegatingDataSourceProcessor{@link DelegatingDataSourceProcessor} 类 + * 动态数据源 @UseDataSource的value值解析处理器(如表达式解析取值等),使用时推荐使用 DelegatingDataSourceProcessor{@link DelegatingDataSourceProcessor} 实例化 * 对动态数据源注解@UseDataSource 增强处理{@link com.mybatisflex.annotation.UseDataSource} * * @author Alay diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java index d52f7ec8..bff2c044 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java @@ -62,7 +62,7 @@ public class FlexMapperProxy extends MybatisMapperProxy { finalDsKey = getMethodDsKey(method, proxy); } - // 对数据源取值进行动态取值处理(#) + // 对数据源取值进行动态取值处理 if (!StrUtil.isBlank(finalDsKey)) { finalDsKey = DataSourceKey.processDataSourceKey(finalDsKey, proxy, method, args); } From 0bcdef685e5de11ea2a25e8fdab5e8729b7fde88 Mon Sep 17 00:00:00 2001 From: chxlay Date: Sat, 7 Dec 2024 17:16:40 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/datasource/processor/DataSourceProcessor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java index 4533f6b5..59f4c5b9 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java @@ -1,5 +1,7 @@ package com.mybatisflex.core.datasource.processor; +import com.mybatisflex.core.mybatis.binding.FlexMapperProxy; + import java.lang.reflect.Method; /** @@ -14,7 +16,7 @@ public interface DataSourceProcessor { /** * 数据源key解析扩展 * - * @param dataSourceKey 注解UseDataSource的value 值,调用process时不会为null,可能会空字符串 + * @param dataSourceKey 注解UseDataSource的value 值,调用process时不会为null,不会为空{@link FlexMapperProxy#invoke(Object, Method, Object[])} * @param mapper Mapper对象(代理对象) * @param method Mapper当前执行的方法函数 * @param arguments Mapper当前执行的函数参数 From 475b0ecb3ad3dc18704b613ce9b64219f66105d6 Mon Sep 17 00:00:00 2001 From: chxlay Date: Mon, 9 Dec 2024 14:56:01 +0800 Subject: [PATCH 6/9] =?UTF-8?q?1=E3=80=81=E5=AF=B9=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90@UseDataSource=E7=9A=84value?= =?UTF-8?q?=E5=80=BC=E8=BF=9B=E8=A1=8C=E5=8A=A8=E6=80=81=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=8C=BA=E5=88=86Spring=E6=A8=A1=E5=BC=8F=E4=B8=8B=E5=92=8C?= =?UTF-8?q?=E9=9D=9ESpring=E6=A8=A1=E5=BC=8F=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatisflex/core/datasource/DataSourceKey.java | 4 ++-- .../core/datasource/DataSourceManager.java | 4 ++-- .../datasource/processor/DataSourceProcessor.java | 6 +++--- .../core/mybatis/binding/FlexMapperProxy.java | 10 +++++----- .../spring/datasource/DataSourceInterceptor.java | 13 +++++++++---- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java index a7f43231..a753ce11 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java @@ -78,8 +78,8 @@ public class DataSourceKey { lookup = threadLocal; } - public static String processDataSourceKey(String dataSourceKey, Object mapper, Method method, Object[] arguments) { - String dsKey = DataSourceManager.processDataSourceKey(dataSourceKey, mapper, method, arguments); + public static String processDataSourceKey(String dataSourceKey, Object targetOrProxy, Method method, Object[] arguments) { + String dsKey = DataSourceManager.processDataSourceKey(dataSourceKey, targetOrProxy, method, arguments); return dsKey != null ? dsKey : dataSourceKey; } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java index ce68caba..79d962bd 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java @@ -109,9 +109,9 @@ public class DataSourceManager { return null; } - static String processDataSourceKey(String dataSourceKey, Object mapper, Method method, Object[] arguments) { + static String processDataSourceKey(String dataSourceKey, Object targetOrProxy, Method method, Object[] arguments) { // 如果没有配置 DataSourceProcessor 实例,则不做处理,返回原始值 - return dataSourceProcessor == null ? dataSourceKey : dataSourceProcessor.process(dataSourceKey, mapper, method, arguments); + return dataSourceProcessor == null ? dataSourceKey : dataSourceProcessor.process(dataSourceKey, targetOrProxy, method, arguments); } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java index 59f4c5b9..a0737b0a 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java @@ -16,12 +16,12 @@ public interface DataSourceProcessor { /** * 数据源key解析扩展 * - * @param dataSourceKey 注解UseDataSource的value 值,调用process时不会为null,不会为空{@link FlexMapperProxy#invoke(Object, Method, Object[])} - * @param mapper Mapper对象(代理对象) + * @param dataSourceKey 注解UseDataSource的value 值,调用process时不会为null,可能为空字符{@link FlexMapperProxy#invoke(Object, Method, Object[])}And{@link com.mybatisflex.spring.datasource.DataSourceInterceptor#getDataSourceKey(Object, Method, Object[])} + * @param targetOrProxy AOP对象this或Mapper代理对象(当注解@UseDataSource使用到Mapper上时为proxy) * @param method Mapper当前执行的方法函数 * @param arguments Mapper当前执行的函数参数 * @return 数据源名称(可能为null 为 null 时表示不符合当前处理器的处理) */ - String process(String dataSourceKey, Object mapper, Method method, Object[] arguments); + String process(String dataSourceKey, Object targetOrProxy, Method method, Object[] arguments); } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java index bff2c044..05e13556 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/binding/FlexMapperProxy.java @@ -59,12 +59,12 @@ public class FlexMapperProxy extends MybatisMapperProxy { try { if (StringUtil.noText(finalDsKey)) { + // Mapper 方法上获取 UseDataSource的value值 finalDsKey = getMethodDsKey(method, proxy); - } - - // 对数据源取值进行动态取值处理 - if (!StrUtil.isBlank(finalDsKey)) { - finalDsKey = DataSourceKey.processDataSourceKey(finalDsKey, proxy, method, args); + // 对数据源取值进行动态取值处理 + if (!StrUtil.isBlank(finalDsKey)) { + finalDsKey = DataSourceKey.processDataSourceKey(finalDsKey, proxy, method, args); + } } // 通过自定义分配策略去获取最终的数据源 diff --git a/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/DataSourceInterceptor.java b/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/DataSourceInterceptor.java index e25d4d4b..2e72d532 100644 --- a/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/DataSourceInterceptor.java +++ b/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/datasource/DataSourceInterceptor.java @@ -19,6 +19,7 @@ package com.mybatisflex.spring.datasource; import com.mybatisflex.annotation.UseDataSource; import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.util.StringUtil; +import com.mybatisflex.processor.util.StrUtil; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.core.MethodClassKey; @@ -44,7 +45,7 @@ public class DataSourceInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { - String dsKey = getDataSourceKey(invocation.getMethod(), invocation.getThis().getClass()); + String dsKey = getDataSourceKey(invocation.getThis(), invocation.getMethod(), invocation.getArguments()); if (StringUtil.noText(dsKey)) { return invocation.proceed(); } @@ -56,11 +57,15 @@ public class DataSourceInterceptor implements MethodInterceptor { } } - private String getDataSourceKey(Method method, Class targetClass) { - Object cacheKey = new MethodClassKey(method, targetClass); + private String getDataSourceKey(Object target, Method method, Object[] arguments) { + Object cacheKey = new MethodClassKey(method, target.getClass()); String dsKey = this.dsCache.get(cacheKey); if (dsKey == null) { - dsKey = determineDataSourceKey(method, targetClass); + dsKey = determineDataSourceKey(method, target.getClass()); + // 对数据源取值进行动态取值处理 + if (!StrUtil.isBlank(dsKey)) { + dsKey = DataSourceKey.processDataSourceKey(dsKey, target, method, arguments); + } this.dsCache.put(cacheKey, dsKey); } return dsKey; From 6e2ae43ea9ee8e4abd705b0d75fd5861a82c3729 Mon Sep 17 00:00:00 2001 From: chxlay Date: Mon, 9 Dec 2024 16:42:05 +0800 Subject: [PATCH 7/9] =?UTF-8?q?1=E3=80=81=E5=AF=B9=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90@UseDataSource=E7=9A=84value?= =?UTF-8?q?=E5=80=BC=E8=BF=9B=E8=A1=8C=E5=8A=A8=E6=80=81=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=8C=BA=E5=88=86Spring=E6=A8=A1=E5=BC=8F=E4=B8=8B=E5=92=8C?= =?UTF-8?q?=E9=9D=9ESpring=E6=A8=A1=E5=BC=8F=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../processor/ParamIndexDataSourceProcessor.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/ParamIndexDataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/ParamIndexDataSourceProcessor.java index 5dbfaec5..b944d163 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/ParamIndexDataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/ParamIndexDataSourceProcessor.java @@ -28,9 +28,13 @@ public class ParamIndexDataSourceProcessor implements DataSourceProcessor { if (arguments.length == 0) return null; Integer index = null; - if (INDEX_FIRST.equals(dataSourceKey)) index = 0; - if (INDEX_LAST.equals(dataSourceKey)) index = arguments.length - 1; - if (dataSourceKey.startsWith(PARAM_INDEX)) index = parseIndex(dataSourceKey); + if (INDEX_FIRST.equals(dataSourceKey)) { + index = 0; + } else if (INDEX_LAST.equals(dataSourceKey)) { + index = arguments.length - 1; + } else if (dataSourceKey.startsWith(PARAM_INDEX)) { + index = parseIndex(dataSourceKey); + } // 没有符合约定的格式输入,则会返回 null if (null == index) return null; From c420adf006107cf71b9d94af059f61daac57f8ac Mon Sep 17 00:00:00 2001 From: chxlay Date: Mon, 30 Dec 2024 11:32:32 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/datasource/processor/DataSourceProcessor.java | 8 ++++++++ .../processor/DelegatingDataSourceProcessor.java | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java index a0737b0a..9ffad5b3 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java @@ -7,6 +7,14 @@ import java.lang.reflect.Method; /** * 动态数据源 @UseDataSource的value值解析处理器(如表达式解析取值等),使用时推荐使用 DelegatingDataSourceProcessor{@link DelegatingDataSourceProcessor} 实例化 * 对动态数据源注解@UseDataSource 增强处理{@link com.mybatisflex.annotation.UseDataSource} + *

+ * 使用区分Spring模式 和 非Spring模式,Spring模式下,代理处理逻辑 DataSourceInterceptor{@link com.mybatisflex.spring.datasource.DataSourceInterceptor} 优先级高于 FlexMapperProxy{@link com.mybatisflex.core.mybatis.binding.FlexMapperProxy} ; + * 所以Spring模式下仅 DataSourceInterceptor 生效(切面生效的前提下)。非Spring 模式下,仅支持注解使用到 Mapper(Dao层),使用到其他层(如Service层)不支持注解解析。 + *

+ * Spring模式下,切面生效的前提下,不区分使用到程序的层(Controller、Service、Dao层都支持),但是建议使用到Mapper层使用注解。其更接近数据操作,更符合控制粒度。 + * 使用在 Controller 和 Service 层则其下层调用的所有操作都会受影响,控制粒度会比较粗,受影响面大。而且容易被下层的注解配置替换上层的注解配置。 + *

+ * 如果同一个调用链多处使用注解 @UseDataSource 则越接近Dao层优先级越高,如 Service 和 Mapper 上同时使用了,则 Service 中解析出来后,当执行 Mapper 时再次解析,会覆盖之前的值。 * * @author Alay * @since 2024-12-07 15:34 diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java index e15f1b92..68d45f7d 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DelegatingDataSourceProcessor.java @@ -10,7 +10,7 @@ import java.util.List; /** * DataSourceProcessor 委托扩展类,对 DataSourceProcessor 结构进行扩大和增强 * 如果多个实例化,建议通过 DelegatingDataSourceProcessor.with(多个解析处理器实例) 方式进行实例化。 - * 需要注意的是委托解析处理器之间有先后顺序,一点排列前面的解析处理器正常处理后,将直接返回处理值,不再往下传递处理 + * 需要注意的是委托解析处理器之间有先后顺序,一旦排列前面的解析处理器正常处理后,将直接返回处理值,不再往下传递处理 * * @author Alay * @since 2024-12-07 15:38 From 91d0e89ee646d81e953d07aed8e3a99aca83f37e Mon Sep 17 00:00:00 2001 From: Alay Date: Thu, 16 Jan 2025 23:55:31 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=E4=B9=A6=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/core/multi-datasource.md | 83 +++++++++++++++++++ .../processor/DataSourceProcessor.java | 5 +- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/docs/zh/core/multi-datasource.md b/docs/zh/core/multi-datasource.md index 1f614431..31cfe0a1 100644 --- a/docs/zh/core/multi-datasource.md +++ b/docs/zh/core/multi-datasource.md @@ -105,6 +105,89 @@ interface AccountMapper extends BaseMapper{ } ``` +`@UseDataSource(value = "#my_expression")`扩展数据源切换,表达式动态读取 key 值 + +- 自定义表达式扩展,对接口 DataSourceProcessor 进行实现,推荐约定动态表达式以 `#` 作为起始标识(当然并不强制做要求) +```java +// 自定义基于Session的表达式取值示例 +public class InSessionDataSourceProcessor implements DataSourceProcessor { + private static final String SESSION_PREFIX = "#session"; + @Override + public String process(String dataSourceKey, Object mapper, Method method, Object[] arguments) { + if (StrUtil.isBlank(dataSourceKey)) return null; + if (!dataSourceKey.startsWith(SESSION_PREFIX)) return null; + + HttpServletRequest request = RequestContextHolder.get.....; + if (null==request) return null; + return request.getSession().getAttribute(dataSourceKey.substring(9)).toString(); + } +} +``` + +- 内置取值表达式取值解析处理器,作为示例参考 + - `DelegatingDataSourceProcessor`,对`DataSourceProcessor`结构进行扩大和增强的委托类,多处理器推荐使用该委托类进行注入,注意委托类内使用`List`委托管理多个解析处理器,执行时有先后顺序。 + - `ParamIndexDataSourceProcessor`,针对简单参数快速取值。 + - `SpelExpressionDataSourceProcessor`,`Spring` 模式下 `SPEL` 表达式取值。 +- 注入动态数据源取值处理器 + +```java +// 注入顺序既为执行时的先后顺序(前面的处理器一旦正确处理,将不会再往下传递处理) +DelegatingDataSourceProcessor dataSourceProcessor = DelegatingDataSourceProcessor.with( + // 参数索引快速取值的 + new ParamIndexDataSourceProcessor(), + // Spel 表达式的 + new SpelExpressionDataSourceProcessor(), + new .....等多个自行扩展表达式() +); +// 实例 setter 赋值 +DataSourceManager.setDataSourceProcessor(dataSourceProcessor); +``` + +- 应用示例: +```java +@Mapper +public interface MyMapper extends BaseMapper{ + // 取值第一个参数的值(arg0的值) + @UseDataSource(value = "#first") + MyEntity testFirst(String arg0, String arg1, String arg2); + + // 取值索引1(第二个参数 arg1 )的值 + @UseDataSource(value = "#index1") + MyEntity testIndex(String arg0, String arg1, String arg2); + + // 取值最后一个参数的值(arg3的值) + @UseDataSource(value = "#last") + MyEntity testLast(String arg0, String arg1, String arg2, String arg3); + + // Spel 表达式取值数据源 + @UseDataSource(value = "#condition.getDsId()") + MyEntity testSpel(MyDatasourceCondition condition); +} +``` + - 调用 +```java +public void test(){ + // mapper中的注解 @UseDataSource(value = "#first") + myMapper.testFirst("my-dskey1", "arg1", "arg2"); + + // 取值索引1(第二个参数)的值;mapper中的注解 @UseDataSource(value = "#index1") + myMapper.testIndex("arg0", "my-dskey2", "arg2"); + + // mapper中的注解 @UseDataSource(value = "#last") + myMapper.testLast("arg0", "arg1", "arg2","my-dskey4"); + + MyDatasourceCondition condition = new MyDatasourceCondition(); + condition.setDsId("my-dskey5"); + // mapper中的注解 @UseDataSource(value = "#condition.getDsId()") + myMapper.testSpel(condition); +} +``` + +- **注意:** + - 1:使用区分`Spring模式`和`非Spring`模式,`Spring`模式下,处理逻辑`DataSourceInterceptor`优先级高于 `FlexMapperProxy`, + 所以`Spring模式下仅 DataSourceInterceptor 生效`(切面生效的前提下)。`非Spring` 模式下,`仅支持注解使用到 Mapper(Dao层)`, + 使用到其他层(如Service层)不支持注解解析。 + - 2:`Spring模式`下,不区分使用到程序的层(Controller、Service、Dao层都支持),下层控制粒度细上层控制粒粗,使用时根据需要进行灵活应用。 `@Table(dataSource="dataSourceName")` 示例: diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java index 9ffad5b3..1de2a6cb 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/processor/DataSourceProcessor.java @@ -11,10 +11,7 @@ import java.lang.reflect.Method; * 使用区分Spring模式 和 非Spring模式,Spring模式下,代理处理逻辑 DataSourceInterceptor{@link com.mybatisflex.spring.datasource.DataSourceInterceptor} 优先级高于 FlexMapperProxy{@link com.mybatisflex.core.mybatis.binding.FlexMapperProxy} ; * 所以Spring模式下仅 DataSourceInterceptor 生效(切面生效的前提下)。非Spring 模式下,仅支持注解使用到 Mapper(Dao层),使用到其他层(如Service层)不支持注解解析。 *

- * Spring模式下,切面生效的前提下,不区分使用到程序的层(Controller、Service、Dao层都支持),但是建议使用到Mapper层使用注解。其更接近数据操作,更符合控制粒度。 - * 使用在 Controller 和 Service 层则其下层调用的所有操作都会受影响,控制粒度会比较粗,受影响面大。而且容易被下层的注解配置替换上层的注解配置。 - *

- * 如果同一个调用链多处使用注解 @UseDataSource 则越接近Dao层优先级越高,如 Service 和 Mapper 上同时使用了,则 Service 中解析出来后,当执行 Mapper 时再次解析,会覆盖之前的值。 + * Spring模式下,不区分使用到程序的层(Controller、Service、Dao层都支持),下层控制粒度细上层控制粒粗,使用时根据需要进行灵活应用。 * * @author Alay * @since 2024-12-07 15:34