springboot2.0.3:读写分离,使用AOP根据方法名动态切换数据源。

springboot版本:2.0.3!!!

springboot版本:2.0.3!!!

springboot版本:2.0.3!!!

我搭好的环境是:springboot 2.0.3+mybatis

大致流程:
方法执行前 -> 切换数据源 -> 执行sql

  • 取消单数据源默认配置
@SpringBootApplication(exclude = {
		DataSourceAutoConfiguration.class
})
public class PalletDemoApplication {
	public static void main(String[] args) {
		SpringApplication.run(PalletDemoApplication.class, args);
	}
}
@Aspect
@Component
@Lazy(false)
@Order(0) //Order设定AOP执行顺序 使之在数据库事务上先执行
public class SwitchDataSourceAOP {
    //这里切到你的方法目录
    @Before("execution(* com.zed.palletdemo.service.*.*(..))")
    public void process(JoinPoint joinPoint) {
        String methodName=joinPoint.getSignature().getName();
        if (methodName.startsWith("get")
                ||methodName.startsWith("count")
                ||methodName.startsWith("find")
                ||methodName.startsWith("list")
                ||methodName.startsWith("select")
                ||methodName.startsWith("check")){
            DataSourceContextHolder.setDbType("selectDataSource");
        }else {
            //切换dataSource
            DataSourceContextHolder.setDbType("updateDataSource");
        }
    }
}

  • 上面用到了一个类:DataSourceContextHolder看他怎么写的
@Component
@Lazy(false)
public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDbType(String dbType) {
        contextHolder.set(dbType);
    }

    public static String getDbType() {
        return contextHolder.get();
    }

    public static void clearDbType() {
        contextHolder.remove();
    }

}
  • 配置两个数据源bean,一会切换
@Configuration
public class DataSourceConfig {

    @Bean(name = "selectDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.select") // application.properteis中对应属性的前缀
    public DataSource dataSource1() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean(name = "updateDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.update") // application.properteis中对应属性的前缀
    public DataSource dataSource2() {
        return DataSourceBuilder.create().build();
    }

}
  • 切面主要切换数据源名称,这里正式生效
@Component
@Primary//不知道什么用,不加报错
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Autowired
    @Qualifier("selectDataSource")
    private DataSource selectDataSource;

    @Autowired
    @Qualifier("updateDataSource")
    private DataSource updateDataSource;

    /**
     * 这个是主要的方法,返回的是生效的数据源名称
     */
    @Override
    protected Object determineCurrentLookupKey() {
        System.out.println("DataSourceContextHolder:::"+DataSourceContextHolder.getDbType());
        return DataSourceContextHolder.getDbType();
    }

    /**
     * 自己配的时候老是报什么没有指定target这里设置一下,默认数据源是updateDataSource
     */
    @Override
    public void afterPropertiesSet() {
        Map<Object,Object> map = new HashMap<>();
        map.put("selectDataSource",selectDataSource);
        map.put("updateDataSource",updateDataSource);
        setTargetDataSources(map);
        setDefaultTargetDataSource(updateDataSource);
        super.afterPropertiesSet();
    }
}
  • 然后service层方法注意一下命名,就可以动态切换了。
  • 我配的两个数据源
spring:
  datasource:
    select:
      jdbc-url: jdbc:mysql://127.0.0.1:3306/test1
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: 123456
    update:
      jdbc-url: jdbc:mysql://127.0.0.1:3306/test2
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: 123456
    type: com.alibaba.druid.pool.DruidDataSource

问题

原文地址:https://www.cnblogs.com/myzoneliver/p/9309664.html