protected Object determineCurrentLookupKey()
/**
* @Description ThreadLocal保存数据源,保持线程隔离
* @Author CJB
* @Date 2020/3/12 14:29
*/
public class DynamicThreadLocalHolder{
//本地线程保存数据源
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
/**
* 设置线程数据源
*/
public static void setDataSource(String dataSource){
threadLocal.set(dataSource);
}
/**
* 获取本地线程的数据源,这里只是数据源的key
* @return
*/
public static String getDataSource(){
return threadLocal.get();
}
/**
* 清除数据源
*/
public static void clearDataSource(){
threadLocal.remove();
}
}
/**
* @Description 动态数据源的实现
* @Author CJB
* @Date 2020/3/12 14:27
*/
public class DynamicDataSourceextends AbstractRoutingDataSource{
/**
* 决定使用哪个数据源
* @return
*/
@Override
protected Object determineCurrentLookupKey(){
//从ThreadLocal中获取数据源的beanName
return DynamicThreadLocalHolder.getDataSource();
}
}
/**
* @Description 数据源的配置
* @Author CJB
* @Date 2020/3/9 13:45
*/
@Configuration
@MapperScan(basePackages = {"com.vivachek.service.dao","com.vivachek.service.dao2"})
public class DatasourceConfig{
/**
* 注入数据源1
*/
@ConfigurationProperties(prefix = "spring.datasource1")
@Bean(value = "dataSource1")
public DataSource dataSource1(){
return new DruidDataSource();
}
/**
* 第二个数据源
*/
@Bean(name = "dataSource2")
@ConfigurationProperties(prefix = "spring.datasource2")
public DataSource dataSource2(){
return new DruidDataSource();
}
/**
* 动态数据源
*
* @return
*/
@Bean
public DynamicDataSource dynamicDataSource(){
DynamicDataSource dataSource = new DynamicDataSource();
//默认数据源,在没有切换数据源的时候使用该数据源
dataSource.setDefaultTargetDataSource(dataSource2());
HashMap<Object, Object> map = Maps.newHashMap();
map.put("dataSource1", dataSource1());
map.put("dataSource2", dataSource2());
//设置数据源Map,动态切换就是根据key从map中获取
dataSource.setTargetDataSources(map);
return dataSource;
}
/**
* 和Mybatis整合必须设置SqlSessionFactory的数据源为动态数据源
*/
@Bean
public SqlSessionFactory sqlSessionFactory()throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
//此处必须设置动态数据源
factoryBean.setDataSource(dynamicDataSource());
factoryBean.setVfs(SpringBootVFS.class);
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
factoryBean.setConfiguration(configuration);
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/**/*.xml"));
return factoryBean.getObject();
}
/**
* 设置事务管理器
*
* @return
*/
@Bean
public PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(dynamicDataSource());
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ChangeSource {
/**
* 数据源,动态数据源默认的是datasource1,这里默认的直接dataSource2
* @return
*/
Stringvalue()default "dataSource1";
}
/**
* @Description 切面
* @Author CJB
* @Date 2020/3/12 16:18
*/
@Aspect
@Component
@Slf4j
public class ChangeSourceAspect{
@Pointcut("@annotation(com.vivachek.core.aop.ChangeSource)")
public void pointcut(){
}
/**
* 在方法执行之前往ThreadLocal中设置值
*/
@Before(value = "pointcut()")
public void beforeOpt(JoinPoint joinPoint){
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
ChangeSource changeSource = method.getAnnotation(ChangeSource.class);
log.info("[Switch DataSource]:" + changeSource.value());
DynamicThreadLocalHolder.setDataSource(changeSource.value());
}
/**
* 结束之后清除
*/
@After(value = "pointcut()")
public void afterOpt(){
DynamicThreadLocalHolder.clearDataSource();
log.info("[change Default DataSource]");
}
}
【数据源】即可。