1、配置数据源,主从两个数据源

/**
 * 多数据源配置(读写主从分离)
 * @author liucc
 */
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {


    public static final String SLAVE_KEY = "slave";
    public static final String MASTER_KEY = "master";

    /**
     * maste setting
     */
    @Bean(initMethod = "init", destroyMethod = "close",name = "masterDataSource")
    @ConfigurationProperties("user.master")
    @Primary
    public DruidDataSource masterDataSource() {
        return new DruidDataSource();
    }


    /**
     * slave setting
     */
    @Bean(initMethod = "init", destroyMethod = "close",name = "slaveDataSource")
    @ConfigurationProperties("user.slave")
    public DruidDataSource slaveDataSource() {
        return new DruidDataSource();
    }


    @Bean(name="dynamicDataSource")
    public ReplicationRoutingDataSource dynamicDataSource(@Qualifier("masterDataSource") DruidDataSource master, @Qualifier("slaveDataSource") DruidDataSource slave) throws IOException {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceConfig.MASTER_KEY, master);
        targetDataSources.put(DataSourceConfig.SLAVE_KEY, slave);

        ReplicationRoutingDataSource dynamicDataSource = new ReplicationRoutingDataSource();
        dynamicDataSource.setDefaultTargetDataSource(master);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }



    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlFactory = new SqlSessionFactoryBean();
        sqlFactory.setDataSource(dataSource);
        sqlFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        return sqlFactory.getObject();
    }

    @Bean
    public DataSourceTransactionManager transactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) throws IOException {
        return new DataSourceTransactionManager(dataSource);
    }
}

2、继承AbstractRoutingDataSource类,实现determineCurrentLookupKey方法动态选择数据源datasource

/**
 * 多数据源路由
 * @author liucc
 */
public class ReplicationRoutingDataSource extends AbstractRoutingDataSource {

    private static final Logger logger = LoggerFactory.getLogger(ReplicationRoutingDataSource.class);

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

    /**
     * Slave if the current transaction is in read-only mode, or master.
     */
    @Override
    protected Object determineCurrentLookupKey() {
        String lookupKey = contextHolder.get();
        if(StringUtils.isBlank(lookupKey)){
            lookupKey = DataSourceConfig.MASTER_KEY;
        }
        logger.info("connected DataSource :{}", lookupKey);
        return lookupKey;
    }

    public static void selectSlave(){
        contextHolder.set(DataSourceConfig.SLAVE_KEY);
    }

    public static void selectMaster(){
        contextHolder.set(DataSourceConfig.MASTER_KEY);
    }
}

3、自定义注解,通过在方法上添加注解来选择需要的数据源

@Documented
@Retention(RUNTIME)
@Target(METHOD)
public @interface SelectDataSource {

    String value() default DataSourceConfig.MASTER_KEY;

}

4、通过Aspect切面来解析注解

/**
 * 数据源自动选择切面
 * @author liucc
 */
@Aspect
@Component
public class DataSourceSelectAspect {

    private static final Logger logger = LoggerFactory.getLogger(DataSourceSelectAspect.class);

    @Before("@annotation(selectDataSource)")
    public void before(SelectDataSource selectDataSource) {
        if(DataSourceConfig.SLAVE_KEY.equals(selectDataSource.value())){
            ReplicationRoutingDataSource.selectSlave();
        }
        else{
            ReplicationRoutingDataSource.selectMaster();
        }
    }

}

5、使用,直接在service方法上添加注解@SelectDataSource

@Service
public class TestService{

    @Autowired
    private UserInfoMapper userInfoMapper;

    @SelectDataSource(DataSourceConfig.SLAVE_KEY)
    public List<User> getUserInfo(String userid){
          return userInfoMapper.get(userid);
    }
}

附上

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
        <setting name="multipleResultSetsEnabled" value="true"/>
        <setting name="useColumnLabel" value="true"/>
        <setting name="useGeneratedKeys" value="true"/>
        <setting name="autoMappingBehavior" value="PARTIAL"/>
        <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
        <setting name="defaultExecutorType" value="SIMPLE"/>
        <setting name="defaultStatementTimeout" value="25"/>
        <setting name="defaultFetchSize" value="100"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="callSettersOnNulls" value="true"/>
        <setting name="logImpl" value="LOG4J2" />
    </settings>
</configuration>

application-db.properties

user.master.url=jdbc:127.0.0.1:3306/user_test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&failOverReadOnly=false&allowMultiQueries=true&useSSL=false
user.master.username=test
user.master.password=test
user.master.initialSize=3
user.master.minIdle=3
user.master.maxActive=5
user.master.maxWait=4
user.master.timeBetweenEvictionRunsMillis=60000
user.master.minEvictableIdleTimeMillis=300000
user.master.testWhileIdle=true
user.master.testOnBorrow=false
user.master.validationQuery=SELECT 1
user.master.driverClassName=com.mysql.jdbc.Driver
user.master.connectionInitSqls=set names utf8mb4


user.slave.url=jdbc:mysql://127.0.0.2:3306/user_test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&failOverReadOnly=false&allowMultiQueries=true&useSSL=false
user.slave.username=test
user.slave.password=test
user.slave.initialSize=3
user.slave.minIdle=3
user.slave.maxActive=5
user.slave.maxWait=4
user.slave.timeBetweenEvictionRunsMillis=60000
user.slave.minEvictableIdleTimeMillis=300000
user.slave.testWhileIdle=true
user.slave.testOnBorrow=false
user.slave.validationQuery=SELECT 1
user.slave.driverClassName=com.mysql.jdbc.Driver
user.slave.connectionInitSqls=set names utf8mb4


                                                                                                                 
06-26 09:46