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