springboot双数据源实现读写分离

1.配置文件中的数据源配置

2.为了方便查询,我将读写分离的代码写在一个包中,如下图

springboot双数据源实现读写分离_第1张图片

3.我们从上向下看,先看annotation包下的

public @interface Master {
}
public @interface Slave {
}

4.bean 包的内容

public class DBContextHolder {
    private static final ThreadLocal contextHolder = new ThreadLocal<>();

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

    public static DBTypeEnum get() {
        return contextHolder.get();
    }

    public static void master() {
        set(DBTypeEnum.MASTER);
    }

    public static void slave() {
        set(DBTypeEnum.SLAVE);
    }
}
@Component
@Primary
public class DynamicDataSource extends AbstractRoutingDataSource {

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

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

    @Override
    protected Object determineCurrentLookupKey() {
        return DBContextHolder.get();
    }
    @Override
    public void afterPropertiesSet() {
        Map map = new HashMap<>();
        map.put(DBTypeEnum.SLAVE,slaveDataSource);
        map.put(DBTypeEnum.MASTER,masterDataSource);
        setTargetDataSources(map);
        setDefaultTargetDataSource(masterDataSource);
        super.afterPropertiesSet();
    }

4.config包内容

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.slave")
    public DataSource slaveDataSource() {
       return DataSourceBuilder.create().build();
    }
}
@Configuration
@EnableTransactionManagement
public class MyBatisConfig extends MybatisAutoConfiguration {

    @Resource(name = "dynamicDataSource")
    private DataSource dynamicDataSource;

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception{
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource);
    }
}

5.enums包内容

public enum DBTypeEnum {
    MASTER, SLAVE
}

6.value中的值可以根据自己的需要进行配置

@Aspect
@Component
@Order(-1)//控制加载顺序,使其最先加载
public class DataSourceHandler {

    @Pointcut(
            value = "!@annotation(com.test.datasource.annotation.Master)"
                    + "&& (execution(* com.test.service..*.select*(..))"
                    + "|| execution(* com.test.service..*.find*(..))"
                    + "|| execution(* com.test.service..*.get*(..))"
                    + "|| execution(* com.test.service..*.query*(..)))"
    )
    private void readPointcut() {

    }

    @Pointcut(
            value = "@annotation(com.test.datasource.annotation.Master)"
                    + "|| execution(* com.test.service..*.insert*(..))"
                    + "|| execution(* ccom.test.service..*.add*(..))"
                    + "|| execution(* com.test.service..*.save*(..))"
                    + "|| execution(* com.test.service..*.update*(..))"
                    + "|| execution(* com.test.service..*.delete*(..))"
                    + "|| execution(* com.test.service..*.remove*(..))"
    )
    private void writePointcut() {

    }

    @Before("readPointcut()")
    private void read() {
    	//从数据源
        DBContextHolder.slave();
    }

    @Before("writePointcut()")
    private void write() {
    	//主数据源
        DBContextHolder.master();
    }
}

7.根据第6不的配置,在service包下,如果方法名以select、find、get、query开头并且在方法上没有加@Master注解,在访问数据库的时候会使用从数据源;如果方法名以insert、add、save、update、delete、remove开头或者方法上加了@Master注解,在访问数据库的时候会使用主数据源

8.该方法是通过互联网查询后自己总结的方法,如果有侵权请联系删除

 

 

你可能感兴趣的:(公共方法)