springboot多数据源《二》

package datachange.mulit.config.config;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * 配置多个库
 *
 * */
@Configuration
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix="spring.datasource.mysql0")
    public DataSource mysql0() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.mysql1")
    public DataSource mysql1() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dynamicDataSource")
    @Primary//使用的时候,只能有一个数据源的事务
    public DynamicDataSource dataSource(@Qualifier("mysql0") DataSource remoteDataSource,@Qualifier("mysql1") DataSource localDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MYSQL0.name(), remoteDataSource);
        targetDataSources.put(DataSourceType.MYSQL1.name(), localDataSource);
        return new DynamicDataSource(remoteDataSource, targetDataSources);
    }

    //设置默认mysql0数据库事务  这与数据源默认DynamicDataAnnonation保持一致
    //多数据源事务保持一致
    //给数据源配置对应的事务管理器,利用编程式事务控制,
    @Bean
    @Primary
    public DataSourceTransactionManager dataSourceTransactionManager0(){
        DataSourceTransactionManager dataSourceTransactionManager=new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(mysql0());
        return dataSourceTransactionManager;
    }

    @Bean("getTransactionTemplate0")
    @Primary
    public TransactionTemplate getTransactionTemplate0(){
        return  new TransactionTemplate(dataSourceTransactionManager0());
    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager1(){
        DataSourceTransactionManager dataSourceTransactionManager=new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(mysql1());
        return dataSourceTransactionManager;
    }

    @Bean("getTransactionTemplate1")
    public TransactionTemplate getTransactionTemplate1(){
        return  new TransactionTemplate(dataSourceTransactionManager1());
    }
}
package datachange.mulit.config.config;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.Map;

/**
 * 集成spring事务
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<String> dataSourceKey = new InheritableThreadLocal<String>();



    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        // afterPropertiesSet()方法调用时用来将targetDataSources的属性写入resolvedDataSources中的
        super.afterPropertiesSet();
    }

    public static void setDataSourceKey(String dataSource) {
        dataSourceKey.set(dataSource);
    }

    public static void toDefault() {
        dataSourceKey.remove();
    }

    @Override

    protected Object determineCurrentLookupKey() {
        return dataSourceKey.get();
    }
}

 

/**
 * 切面
 */
@Aspect
@Component
public class DynamicDataSourceAspect {
    @Pointcut("@annotation(security.config.dynamic.DynamicSource)")
    public void dataSourcePointCut(){

    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String dsKey = getDSAnnotation(joinPoint).value();
        DynamicDataSource.setDataSourceKey(dsKey);
        try{
            return joinPoint.proceed();
        }finally {
            DynamicDataSource.toDefault();
        }
    }

    /**
     * 根据类或方法获取数据源注解
     */
    private DynamicSource getDSAnnotation(ProceedingJoinPoint joinPoint){
        Class<?> targetClass = joinPoint.getTarget().getClass();
        DynamicSource dsAnnotation = targetClass.getAnnotation(DynamicSource.class);
        // 先判断类的注解,再判断方法注解
        if(Objects.nonNull(dsAnnotation)){
            return dsAnnotation;
        }else{
            MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
            return methodSignature.getMethod().getAnnotation(DynamicSource.class);
        }
    }
}

 

使用

    /**
     * 查询master库User
     */
    @DynamicSource(DataSourceType.MYSQL0)
    public List getMasterUser() {
       return null;
    }

    /**
     * 查询slave库User
     */
    @DynamicSource(DataSourceType.MYSQL1)
    public List getSlaveUser() {
        return null;
    }

 

注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicSource {
    String value() default MYSQL0;
}

 

简要介绍多数据源,声明式事务

 

源码地址:https://gitee.com/wbweb/spring-boot-mulit-transaltion

 

posted @ 2022-07-02 19:33  余生请多指教ANT  阅读(64)  评论(0编辑  收藏  举报