springboot2.0.3:讀寫分離,使用AOP根據方法名動態切換數據源。

springboot版本:2.0.3!!!

springboot版本:2.0.3!!!

springboot版本:2.0.3!!!

我搭好的環境是:springboot 2.0.3+mybatismysql

大體流程: 方法執行前 -> 切換數據源 -> 執行sqlspring

  • 取消單數據源默認配置
@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

問題

相關文章
相關標籤/搜索