spring bootSpring BootJava学习笔记

spring boot动态数据源

2017-06-27  本文已影响411人  jey恒

基于spring boot

大概结构

image.png

使用

@EnableDynamicDataSource
@Configurable
@MapperScan(basePackageClasses = DaoConfig.class)
@EnableTransactionManagement(proxyTargetClass = true)
public class DaoConfig {


  @Autowired
  private DataSource dataSource;

  @Bean
  public PlatformTransactionManager txManager() {
    return new DataSourceTransactionManager(dataSource);
  }

}


#数据源配置
datasource.master.driver-class-name=com.mysql.jdbc.Driver
datasource.master.url=jdbc:mysql://xxxx:3306/test?useUnicode=true&characterEncoding=UTF-8
datasource.master.username=xxx
datasource.master.password=xxx

# 多个从库names=one,two,tree逗号隔开就好
datasource.slave.names=one
datasource.slave.one.driver-class-name=com.mysql.jdbc.Driver
datasource.slave.one.url=jdbc:mysql://xxxx:3306/test_slave?useUnicode=true&characterEncoding=UTF-8
datasource.slave.one.username=xxx
datasource.slave.one.password=xxx


# 数据注册公用配置 【druid,其他的数据源参考对于的属性配置即可 type配置数据源类型】
datasource.common.type=com.alibaba.druid.pool.DruidDataSource
datasource.common.initial-size=1
datasource.common.min-idle=1
datasource.common.max-active=30
datasource.common.test-on-borrow=true
datasource.common.max-wait=60000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
datasource.common.timeBetweenEvictionRunsMillis=60000
#配置一个连接在池中最小生存的时间,单位是毫秒
datasource.common.minEvictableIdleTimeMillis=300000
datasource.common.testWhileIdle=true
datasource.common.testOnBorrow=false
datasource.common.testOnReturn=false
datasource.common.validationQuery=SELECT 'x'
datasource.common.poolPreparedStatements=true
datasource.common.maxOpenPreparedStatements=20

在service的实现类中使用

 @SelectDataSource(type = DataSourceType.SLAVE)
public Object getxxx(){
return xxx;
}

流程

// 读取配置文件,注册DynamicRoutingDataSource
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {


  /** 主库 */
  @Getter
  @Setter
  private DataSource master;

  /** 多个从库 */
  @Getter
  @Setter
  private List<DataSource> slaveList;

  /** 路由策略 */
  @Getter
  @Setter
  private DataSourceRoute dataSourceRoute;
}
@Order(1)
@Slf4j
@Aspect
public class DynamicDatasourceAspect {


// 切点  @Pointcut("@annotation(com.yyfq.io.common.datasource.SelectDataSource)")
  public void aspectMethod() {}

  /**
   * 切点 环绕
   * 
   * @param joinPoint
   * @return
   * @throws Throwable
   */
  @Around("aspectMethod()")
  public Object dynamicDataSource(ProceedingJoinPoint joinPoint) throws Throwable {

    try {

      SelectDataSource dataSource = get(joinPoint);

      if (Objects.nonNull(dataSource)) {
        DataSourceType dataSourceType = dataSource.type();
        DataSourceHolder.setLookUpKey(dataSourceType);
      }

      return joinPoint.proceed();

    } catch (Throwable e) {
      throw e;
    } finally {

      DataSourceHolder.clear();
    }

  }


public class DataSourceHolder {

  private final static ThreadLocal<DataSourceType> lookUpKey = new ThreadLocal<>();

// 方法中多个业务sql, 简单的路由缓存
  private final static ThreadLocal<DataSource> nowDataSource = new ThreadLocal<>();

  public static void clear() {

    lookUpKey.remove();
    nowDataSource.remove();
  }


// 模板子类实现 路由策略获取一个数据源
@Override
  protected DataSource routTarget0(List<DataSource> dataSourceList) {
    DataSource dataSource = dataSourceList.get(random(dataSourceList));
    return dataSource;
  }


  private int random(List<DataSource> dataSourceList) {

    if (dataSourceList.size() == 1) {
      return 0;
    }

    return RandomUtils.nextInt(0, dataSourceList.size());
  }

上一篇 下一篇

猜你喜欢

热点阅读