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]"); } }
【数据源】即可。