springboot多数据源注解配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      slave1:
        filters: stat
        driver-class-name: oracle.jdbc.OracleDriver
        url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
        username: root
        password: root
      master:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/aliyun-jdy?characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=UTC
        username: root
        password: root
package com.xxx.common;
/**
 * @author
 * @Date
 */
public class DataSourceContextHolder {
    public static final String MASTER = "master";
    public static final String SLAVE_1 = "slave1";

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

    public static void setDataSource(String name) {
        contextHolder.set(name);
    }

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

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

}

package com.xxx.common;

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

/**
 * @author
 * @Date
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }

}

package com.xxx.common;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

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

/**
 * @author
 * @Date
 */
@Configuration
public class MultipleDateSourceConfig {

    @Bean(DataSourceContextHolder.MASTER)
    @ConfigurationProperties(prefix = "spring.datasource.druid.master")
    public DataSource createMasterDataSource() {
        return new DruidDataSource();
    }

    @Bean(DataSourceContextHolder.SLAVE_1)
    @ConfigurationProperties(prefix = "spring.datasource.druid.slave1")
    public DataSource createSlave1DataSource() {
        return new DruidDataSource();
    }

    /**
     * 设置动态数据源,通过@Primary 来确定主DataSource
     *
     * @return
     */
    @Bean
    @Primary
    public DataSource createDynamicDataSource(@Qualifier(DataSourceContextHolder.MASTER) DataSource master, @Qualifier(DataSourceContextHolder.SLAVE_1) DataSource slave1) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        //设置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(master);
        //配置多数据源
        Map<Object, Object> map = new HashMap<>();
        map.put(DataSourceContextHolder.MASTER, master);
        map.put(DataSourceContextHolder.SLAVE_1, slave1);
        dynamicDataSource.setTargetDataSources(map);
        return dynamicDataSource;
    }

}

package com.xxx.annotation;

import com.dhht.web.common.DataSourceContextHolder;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 
 * @Date
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DataSource {
    String value() default DataSourceContextHolder.MASTER;
}
package com.xxx.common;

import com.dhht.web.annotation.DataSource;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.SQLException;

/**
 * @author
 * @Date
 */
@Aspect
@Component
public class DynamicDataSourceAspect {

    @Resource
    protected ApplicationContext applicationContext;

    private Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

    //切入点只对@Service注解的类上的@DataSource方法生效
    //@Pointcut(value = "@within(org.springframework.stereotype.Service) && @annotation(dataSource)")
    @Pointcut(value = "@target(org.springframework.stereotype.Service) && @annotation(com.dhht.web.annotation.DataSource)")
    public void dynamicDataSourcePointCut() {
    }

    //@Before(value = "dynamicDataSourcePointCut(dataSource)")
    @Before(value = "dynamicDataSourcePointCut()")
    public void switchDataSource(JoinPoint joinPoint) throws Throwable {
        DataSource dataSource = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(DataSource.class);
        if ((null == dataSource)) {
            return;
        }
        logger.info("切换数据源为**:{}", dataSource.value());
        DataSourceContextHolder.setDataSource(dataSource.value());
    }

    //@After(value = "dynamicDataSourcePointCut(dataSource)")
    @After(value = "dynamicDataSourcePointCut()")
    public void after() {
        DataSourceContextHolder.cleanDataSource();
        logger.info("再次切换数据源为:master");
        DataSourceContextHolder.setDataSource("master");
    }

    //@Pointcut("execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")
    //@Pointcut("within(com.test.spring.aop.pointcutexp..*)")
    //@Pointcut("this(com.test.spring.aop.pointcutexp.Intf)")
    //@Pointcut("target(com.test.spring.aop.pointcutexp.Intf)")
    //@Pointcut("@within(org.springframework.transaction.annotation.Transactional)")
    //@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
    //定义切点
    @Pointcut("execution(* com.dhht..service..*.*(..))")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void before(JoinPoint joinPoint) throws SQLException {
        javax.sql.DataSource bean = applicationContext.getBean(javax.sql.DataSource.class);
        //if ((bean instanceof DynamicDataSource)) {
        //    DynamicDataSource dynamicDataSource = (DynamicDataSource) bean;
        //    logger.info("current tx datasource=" + dynamicDataSource.getConnection().toString());
        //    return;
        //}

        logger.info("current target services=" + joinPoint.getTarget().toString());
        logger.info("current tx datasource=" + bean.getClass().getName());
        return;
    }

}
posted @ 2022-11-18 16:37  qing222  阅读(416)  评论(0编辑  收藏  举报