SpringBoot+Aop动态切换数据源

1、yml数据源配置

spring:
  mvc:
    throw-exception-if-no-handler-found: true
    static-path-pattern: /static/**
  datasource:
    master:
      driver-class-name: com.mysql.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/master?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: root
    save:
      driver-class-name: com.mysql.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/save?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: root

2、自定义注解

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited  //可以继承
public @interface DB {
    String value();
}

3、切换数据源类

public class DynamicDataSource extends AbstractRoutingDataSource {

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

	//这个可写可不写,甚至可以忽略
	public static ThreadLocal<String> getContextholder() {
        return contextHolder;
    }


    /**
     * 切换数据源
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }

    /**
     * 设置数据源
     * @param dataSorce
     */
    public static void setDataSorce(String dataSorce){
        contextHolder.set(dataSorce);
    }

    /**
     * 获取数据源
     * @return
     */
    public static String getDataSource(){
        return contextHolder.get();
    }

    /**
     * 清除数据源
     */
    public static void clearDataSource(){
        contextHolder.remove();
    }
}

4、数据源配置类

@Configuration
public class DataSourceConfig {

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

    @Bean
    @ConfigurationProperties("spring.datasource.save")
    public DataSource dataSourceSave(){
        return DataSourceBuilder.create().build();
    }


    @Primary
    @Bean
    public DataSource dynamicDataSource(){
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        //设置默认的数据源
        dynamicDataSource.setDefaultTargetDataSource(dataSourceMaster());

        //添加数据源
        Map<Object,Object> dBMap = new HashMap<>();
        dBMap.put("master",dataSourceMaster());
        dBMap.put("save",dataSourceSave());
        dynamicDataSource.setTargetDataSources(dBMap);
        return dynamicDataSource;
    }


    /**
     * 添加事务
     * @return
     */
    @Bean
    public PlatformTransactionManager platformTransactionManager(){
        return new DataSourceTransactionManager(dynamicDataSource());
    }
 }

5、Aop切面动态切换数据源
5.1:注意:这里判断的是方法上注解,目前判断类上的注解就会报错,找不到表,后面研究下类上的注解,然后再做修改,报错如下:
在这里插入图片描述

@Order(-1)
@Aspect
@Component
public class DynamicDataSourceAspect {


    @Pointcut("@annotation(com.alibaba.config.datasourceconf.DB)")
    public void ponincut(){}

    @SuppressWarnings("rawtypes")
//    @Before("@annotation(com.alibaba.config.datasourceconf.DB) || @within(com.alibaba.config.datasourceconf.DB)")
    @Before("ponincut()")
    public void beforeAspect(JoinPoint joinPoint){

        //获取当前访问的类名
        Class<?> className = joinPoint.getTarget().getClass();
        System.out.println("当前类:"+className);

        //获取当前访问方法名
        String methodName = joinPoint.getSignature().getName();
        System.out.println("当前方法名:"+methodName);

        //获取当前访问的参数类型
        Class[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        for (Class parameterType : parameterTypes) {
            System.out.println("参数类型:"+parameterType);
        }
        //获取当前访问的参数名字
        String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        for (String parameterName : parameterNames) {
            System.out.println("参数名字:"+parameterName);
        }
        //获取当前的参数值
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            System.out.println("参数值:"+arg);
        }
        //获取当前的数据源
        String defaultdb = DynamicDataSource.DEFAULTDB;

        try {
            //获取当前方法的对象
            Method method = className.getMethod(methodName, parameterTypes);
            System.out.println("当前的对象1:"+method);
            DB classAnnotion = className.getAnnotation(DB.class);
            System.out.println(classAnnotion);
            //判断是否有DB该注解
            if (method.isAnnotationPresent(DB.class)){
                //获取当前方法的DB注解
                DB annotation = method.getAnnotation(DB.class);
                System.out.println("当前方法的注解:"+annotation);
                //获取当前注解的值
                defaultdb = annotation.value();
                System.out.println("当前注解的值:"+defaultdb);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //切换数据源
        DynamicDataSource.setDataSorce(defaultdb);
    }

    /**
     * 清除数据源
     */
    @After("ponincut()")
    public  void afterAspect(){
        DynamicDataSource.clearDataSource();
    }
}

6、实现类

@Service
public class DymincDataServiceImpl implements DymincDataService {

    @Autowired
    private DymincDataMapper dymincDataMapper;

	// 这里查询的是save数据源
    @Override
    @DB(value = "save")
    public PageInfo<CheckItem> findCheck(Integer currentPage, Integer pageSize) {
        PageHelper.startPage(currentPage,pageSize);
        List<CheckItem> check = dymincDataMapper.findCheck();
        PageInfo<CheckItem> checkItemPageInfo = new PageInfo<>(check);
        return checkItemPageInfo;
    }

//这里没有注解就是默认的数据源
@Override
public PageInfo<Test> findTest(Integer currentPage, Integer pageSize) {
    PageHelper.startPage(currentPage,pageSize);
    List<Test> test = dymincDataMapper.findTest();
    PageInfo<Test> testPageInfo = new PageInfo<>(test);
    return testPageInfo;
   }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值