天天看点

SpringAop数据源切换(AbstractRoutingDataSource使用)

数据源切换

1.定义AbstractRoutingDataSource,使其能够支持多个数据源

@Component("dataSource")
@Primary
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Autowired
    @Qualifier("readDataSource")
    private DataSource readDataSource;

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

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDbType();
    }

    @Override
    public void afterPropertiesSet() {
        Map<Object,Object> map = new HashMap<>();
        map.put("readDataSource",readDataSource);
        map.put("writeDataSource",writeDataSource);
        setTargetDataSources(map);
        setDefaultTargetDataSource(writeDataSource);
        super.afterPropertiesSet();
    }
}

           

2.数据库切换类

@Component
@Lazy(false)
public class DataSourceContextHolder {

    public static final String WRITE_DATA_SOURCE = "writeDataSource";
    public static final String READ_DATA_SOURCE = "readDataSource";

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

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

    public static String getDbType() {
        return contextHolder.get();
    }

    public static void clearDbType() {
        contextHolder.remove();
    }
}

           

3.通过AOP在切面确定数据源

@Aspect
@Component
@Lazy(false)
@Order(0)
public class SwitchDataSourceAOP {
    @Before("execution(* com.mapper.*.*(..)) " )
    public void process(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        if (methodName.startsWith("get")
                ||  other Condition ) {
            DataSourceContextHolder.setDbType(DataSourceContextHolder.READ_DATA_SOURCE);
        } else {
            DataSourceContextHolder.setDbType(DataSourceContextHolder.WRITE_DATA_SOURCE);
        }
    }
}

           

4.事务时候选择数据源

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
public class DynamicTransactionManagerConfig implements TransactionManagementConfigurer {

    @Autowired
    private DynamicDataSource dataSource;

    @Override
    @Bean
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return new DynamicDataSourceTransactionManager(dataSource);
    }
}
           
public class DynamicDataSourceTransactionManager extends DataSourceTransactionManager {
    public DynamicDataSourceTransactionManager(DataSource dataSource) {
        super(dataSource);
    }

    @Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        if (!definition.isReadOnly()) {
            DataSourceContextHolder.setDbType(DataSourceContextHolder.WRITE_DATA_SOURCE);
        }
        super.doBegin(transaction, definition);
    }

    @Override
    protected void doCleanupAfterCompletion(Object transaction) {
        DataSourceContextHolder.clearDbType();
        super.doCleanupAfterCompletion(transaction);
    }
}