MyBatis-Plus动态数据源需要导入jar包com.baomidoudynamic-datasource-spring-boot-starter3.3.1使用@DS()注解,括号中的值为我们配置的数据源名称,通常配置为mapper层的class;如果没有这个注解,则使用Thedefaultdatabase为默认数据库;@DS的优先级也是就近原则。如果类上有@DS,并且它的某个方法也有@DS,那么该方法使用的数据库就是该方法上声明的数据库;有时不同的库有相同的表(对应一个实体类)需要在运行时动态选择数据源。我们可以在使用@DS注解时使用#wildcards来启用我们的数据库作为参数;#parameternames可以动态使用我们的参数变量或者header和session中的变量;'#'参数的实现依赖于com.baomidou.dynamic.datasource.processorDsProcessor接口处理,DsHeaderProcessor的实现有以下三种:从请求的header中获取ds数据源名称。DsSessionProcessor:从会话中获取数据源d的名称DsSpelExpressionProcessor:通过spel表达式获取ds数据源的名称。这三个方法是在责任链中连续获取的。依次执行。DsHeaderProcessor的拦截格式为@DS("#header变量名")@DS("#headerdataName")ListList(@Param("query")StringqueryDsSessionProcessor拦截格式为@DS("#sessionvariableName")@DS("#sessiondataName")ListList(@Param("query")Stringquery@DS("#dataName")ListList(@Param("query")Stringquery,StringdataName);其实现原理为DynamicDataSourceAutoConfiguration配置类Advisor@Bean@ConditionalOnMissingBeanpublicDynamicDataSourceAnnotationAdvisordynamicDatasourceAnnotationAdvisor(DsProcessordsProcessor){DynamicDataSourceAnnotationInterceptorinterceptor=newDynamicDataSourceAnnotationInterceptor();interceptor.setDsProcessor(dsProcessor);DynamicDataSourceAnnotationAdvisoradvisor=newDynamicDataSourceAnnotationAdvisor(interceptor);advisor.setOrder(properties.getOrder());returnadvisor;}DynamicDataSourceAnnotationAdvisor的切点是DS注解privatePointcutbuildPointcut(){切入点cpc=newAnnotationMatchingPointcut(DS.class,true);切入点mpc=AnnotationMatchingPointcut.forMethodAnnotation(DS.class);返回新的ComposablePointcut(cpc).union(mpc);}拦截器为DynamicDataSourceAnnotationInterceptor,拦截器会处理#开头的Annotation值,交给DsProcessor处理privatestaticfinalStringDYNAMIC_PREFIX="#";privateStringdetermineDatasource(MethodInvocationinvocation)throwsThrowable{Methodmethod=invocation.getMethod();DSds=method.isAnnotationPresent(DS.class)?method.getAnnotation(DS.class):AnnotationUtils.findAnnotation(RESOLVER.targetClass(invocation),DS.class);字符串键=ds.value();返回(!key.isEmpty()&&key.startsWith(DYNAMIC_PREFIX))?dsProcessor.determineDatasource(invocation,key):key;}DsHeaderProcessor处理逻辑是从请求的header中获取变量值:privatestaticfinalStringHEADER_PREFIX="#header";@Override公共布尔值matches(Stringkey){returnkey.startsWith(HEADER_PREFIX);}@OverridepublicStringdoDetermineDatasource(MethodInvocationinvocation,Stringkey){HttpServletRequestrequest=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();/可以看出HEADER_PREFIX和数据源之间需要有一个空格,可以返回任意字符request.getHeader(key.substring(8));}DsSessionProcessor从会话中获取变量的值:privatestaticfinalStringSESSION_PREFIX="#session";@Overridepublicbooleanmatches(Stringkey){returnkey.startsWith(SESSION_PREFIX);}@OverridepublicStringdoDetermineDatasource(MethodInvocationinvocation,Stringkey){HttpServletRequestrequest=((ServletRequestAttributes.());//这一行说明SESSION_PREFIX和数据源之间需要有一个空格,可以进行任意字符返回请求.getSession().getAttribute(key.substring(9)).toString();}DsSpelExpressionProcessor:/***参数查找器*/privatestaticfinalParameterNameDiscovererNAME_DISCOVERER=newDefaultParameterNameDiscoverer();/***Express语法解析器*/privatestaticfinalExpressionParserPARSER=newSpelExpressionParser();@Overridepublicbooleanmatches(Stringkey){returntrue;}@OverridepublicStringdoDetermineDatasource(MethodInvocationinvocation,Stringkey){Methodmethod=invocation.getMethod();对象[]arguments=invocation.getArguments();EvaluationContextcontext=newMethodBasedEvaluationContext(null,method,arguments,NAME_DISCOVERER);finalObject.value=PARSCOVERERparseExpression(key).getValue(context);返回值==空?null:值.toString();具体实现原理可以参考Spring动态数据源。源码入口为:`com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration