通过注解配置多数据源切换

配置



    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
    




    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
    





    
      
        
        
      
    
    
    







    
      
      
      
      
    

注意:此切面的优先级要高于事务的优先级

注解类

注解可作用于方法、接口、类上

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomDataSource {

  String value();

  String D01 = "dataSource01";

  String D02 = "dataSource02";

}

切面类

public class DataSourceAspect {
  /**
   * 拦截目标方法,通过注解来获取数据源名称key值,设置到ThreadLocal中
   */
  public void intercept(JoinPoint point) throws Exception {
    Class target = point.getTarget().getClass();
    MethodSignature signature = (MethodSignature) point.getSignature();
    // 使用目标注解类型,如果没有,则使用其接口指定类型
    for (Class clazz : target.getInterfaces()) {
      resolveDataSource(clazz, signature.getMethod());
    }
    resolveDataSource(target, signature.getMethod());
  }

  /**
   * 获取目标对象方法注解和类型注解中的注解
   */
  private void resolveDataSource(Class clazz, Method method) {
    try {
      Class[] types = method.getParameterTypes();
      // 默认使用类型注解
      if (clazz.isAnnotationPresent(CustomDataSource.class)) {
        CustomDataSource cds = clazz.getAnnotation(CustomDataSource.class);
        BindingDataSourceKey.setDataSourceToken(cds.value());
      }
      // 方法注解覆盖,以方法注解为最后值
      Method m = clazz.getMethod(method.getName(), types);
      if (m != null && m.isAnnotationPresent(CustomDataSource.class)) {
        CustomDataSource cds = m.getAnnotation(CustomDataSource.class);
        BindingDataSourceKey.setDataSourceToken(cds.value());
      }
    } catch (Exception e) {
      log.error(clazz + ":" + e.getMessage());
    }
  }

}

ThreadLocal 类

public class BindingDataSourceKey {
    private static final ThreadLocal THREAD_LOCAL_TOKEN = new ThreadLocal();
    
    public static String getDataSourceToken() {
        return THREAD_LOCAL_TOKEN.get();
    }
    
    public static void setDataSourceToken(String dataSource) {
        THREAD_LOCAL_TOKEN.set(dataSource);
    }
    
    public static void clearDataSourceToken() {
        THREAD_LOCAL_TOKEN.remove();
    }
}

获取数据源对应key的类

public class DynamicDataSource extends AbstractRoutingDataSource {
  @Override
  protected Object determineCurrentLookupKey() {
    String dataSource = BindingDataSourceKey.getDataSourceToken();
    // 获取完后解除绑定,防止其他的service方法调用该数据源
    BindingDataSourceKey.clearDataSourceToken();
    return dataSource;
  }
}

之后需要在注解的类上、方法或是接口上加上注解@CustomDataSource(CustomDataSource.D02),就可以通过切入点表达式进行获取注解情况,从而控制数据源

你可能感兴趣的:(通过注解配置多数据源切换)