天天看點

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);
    }
}