MyBatis-Plus 动静数据源须要引入jar包

<dependency>    <groupId>com.baomidou</groupId>    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>    <version>3.3.1</version></dependency>

应用@DS()注解,括号内的值是咱们配置的数据源名称,通常应用的时候是配置到mapper层的类上;如果没有该注解则应用的是默认数据库;
@DS 的优先级也是就近准则,如果类上已有@DS且他的某个办法也有@DS那么该办法应用的数据库为办法上申明的数据库;
有些时候不同库中有雷同的表(对应一个实体类),须要在运行时动静抉择数据源。咱们能够在应用@DS注解的时候,应用#通配符,将咱们的数据库以参数的形式来启用;#参数名称能够动静的应用咱们的参数变量或者header和session中的变量;

‘#’参数的实现依赖于com.baomidou.dynamic.datasource.processorDsProcessor接口解决,实现形式有三个

  1. DsHeaderProcessor: 从申请的header中获取ds数据源名称。
  2. DsSessionProcessor: 从session中获取数据源d名称
  3. DsSpelExpressionProcessor: 通过spel表达式获取ds数据源名称,

这3种形式采纳的是责任链形式间断获取的。顺次执行。

DsHeaderProcessor的拦挡格局为@DS("#header 变量名")@DS("#header dataName")List<Entity> List(@Param("query") String queryDsSessionProcessor的拦挡格局为@DS("#session 变量名")@DS("#session dataName")List<Entity> List(@Param("query") String query@DS("#dataName")List<Entity> List(@Param("query") String query, String dataName);

其实现原理为DynamicDataSourceAutoConfiguration配置类Advisor

  @Bean  @ConditionalOnMissingBean  public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) {    DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor();    interceptor.setDsProcessor(dsProcessor);    DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);    advisor.setOrder(properties.getOrder());    return advisor;  }

DynamicDataSourceAnnotationAdvisor的切点为DS注解

  private Pointcut buildPointcut() {    Pointcut cpc = new AnnotationMatchingPointcut(DS.class, true);    Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(DS.class);    return new ComposablePointcut(cpc).union(mpc);  }

拦截器为DynamicDataSourceAnnotationInterceptor,拦截器会解决以#结尾的注解值,并交由
DsProcessor来解决

  private static final String DYNAMIC_PREFIX = "#";  private String determineDatasource(MethodInvocation invocation) throws Throwable {    Method method = invocation.getMethod();    DS ds = method.isAnnotationPresent(DS.class)        ? method.getAnnotation(DS.class)        : AnnotationUtils.findAnnotation(RESOLVER.targetClass(invocation), DS.class);    String key = ds.value();    return (!key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) ? dsProcessor        .determineDatasource(invocation, key) : key;  }

DsHeaderProcessor解决逻辑为从request的header中取变量值:

  private static final String HEADER_PREFIX = "#header";  @Override  public boolean matches(String key) {    return key.startsWith(HEADER_PREFIX);  }  @Override  public String doDetermineDatasource(MethodInvocation invocation, String key) {    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder        .getRequestAttributes()).getRequest();//这一行能够看出HEADER_PREFIX 和数据源之间须要空一位,能够使任意字符    return request.getHeader(key.substring(8));  }

DsSessionProcessor 从seesion中去取变量的值:

  private static final String SESSION_PREFIX = "#session";  @Override  public boolean matches(String key) {    return key.startsWith(SESSION_PREFIX);  }  @Override  public String doDetermineDatasource(MethodInvocation invocation, String key) {    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder        .getRequestAttributes()).getRequest();//这一行能够看出SESSION_PREFIX 和数据源之间须要空一位,能够使任意字符    return request.getSession().getAttribute(key.substring(9)).toString();  }

DsSpelExpressionProcessor:

  /**   * 参数发现器   */  private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();  /**   * Express语法解析器   */  private static final ExpressionParser PARSER = new SpelExpressionParser();  @Override  public boolean matches(String key) {    return true;  }  @Override  public String doDetermineDatasource(MethodInvocation invocation, String key) {    Method method = invocation.getMethod();    Object[] arguments = invocation.getArguments();    EvaluationContext context = new MethodBasedEvaluationContext(null, method, arguments,        NAME_DISCOVERER);    final Object value = PARSER.parseExpression(key).getValue(context);    return value == null ? null : value.toString();  }

具体的实现原理能够参考 Spring 动静数据源,源码入口为:`
com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration