Spring Boot多数据源配置实现读写分离

本文详细介绍在SpringBoot中实现数据库读写分离的方法,通过自定义数据源路由和使用AspectJ切面技术,动态切换主从数据源,提高数据库访问效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境概览

  1. Spring Boot 2.1.0.RELEASE
  2. AspectJ Weaver 1.9.2
  3. Mysql 5.6.28 

前言介绍

    在日常的项目开发中,存在某些sql查询效率低,或因为并发瓶颈受限于数据库。所以我们需要实现读写分析,对于慢sql,或者大并发的sql查询语句,实现读写分离,负载均衡。在技术上,目前有很多JAVA中间件可以实现读写分离,例如当当的Sharding-JDBC,美团的DBProxy等。本文将介绍如何在Spring Boot中不依赖第三方框架配置读写分离。

项目结构

   

项目地址

GitHub传送门

具体实现

  • 实现AbstractRoutingDataSource抽象方法,动态切换数据源
    @Bean
    public AbstractRoutingDataSource routingDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<Object, Object>(2);
        targetDataSources.put(DataSourceContextHolder.MASTER, masterDataSource);
        targetDataSources.put(DataSourceContextHolder.SLAVE, slaveDateSource);
        // 路由类,寻找对应的数据源
        AbstractRoutingDataSource proxy = new AbstractRoutingDataSource() {
            @Override
            protected Object determineCurrentLookupKey() {
                String key = DataSourceContextHolder.getMaterOrSlave();
                if (key == null) {
                    return DataSourceContextHolder.MASTER;
                }
                return key;
            }
        };

        // 默认库
        proxy.setDefaultTargetDataSource(masterDataSource);
        proxy.setTargetDataSources(targetDataSources);
        return proxy;
    }
  • 创建切面选择数据源
@EnableAspectJAutoProxy
@Aspect
@Component
public class DataSourceChangeAop {

    private final String slaveAop = "@annotation(com.noral.multidatasource.configuration.annotation.SlaveDataSource)";

    private final String masterAop = "@annotation(com.noral.multidatasource.configuration.annotation.MasterDataSource)";

    @Before(slaveAop)
    public void changeToSlaveDataSource() {
        DataSourceContextHolder.setSlave();
    }


    @Before(masterAop)
    public void changeToMasterDataSource() {
        DataSourceContextHolder.setMaster();
    }

    @After("(" + slaveAop + "||" + masterAop + ")")
    public void after() {
        DataSourceContextHolder.clear();
    }
}
  • 创建方法测试
@Service
public class PersonServiceImpl implements PersonService {


    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public Person getPerson() {
        Person person = jdbcTemplate.queryForObject("select  * from person", new BeanPropertyRowMapper<>(Person.class));
        return person;
    }


    @Override
    @SlaveDataSource
    public Person getPersonSlave() {
        Person person = jdbcTemplate.queryForObject("select  * from person", new BeanPropertyRowMapper<>(Person.class));
        return person;
    }

    @Override
    @MasterDataSource
    public Person getPersonMaster() {
        Person person = jdbcTemplate.queryForObject("select  * from person", new BeanPropertyRowMapper<>(Person.class));
        return person;
    }

}

结果

     @Test
    public void testForChangeDataSource() {
        System.out.println(personService.getPerson());
        //Person{id=1, name='datasource1'}
        System.out.println(personService.getPersonSlave());
        //Person{id=2, name='datasource2'}
        System.out.println(personService.getPersonMaster());
        //Person{id=1, name='datasource1'}
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值