项目开发过程中,经常出现数据库迁移,但是有些数据还得访问老数据库,当然还有别的需求,需要项目中访问多个数据源。本章内容,主要使用aop实现双数据源的动态切换。框架:springboot
废话不多说,直接看下文。。。
1、引入aop依赖
<!-- aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、设置数据源参数
在主启动类上,排除数据源自动配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) //排除数据源自动配置,使用自定义配置
3、配置DataSourceConfig
4、创建动态数据源DynamicDataSource
//设置数据源
5、DataSource切面
自定义注解:@DataSource
aop切面:DataSourceAspect
@Component
@Aspect
public class DataSourceAspect {
private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);
// 指定切入点表单式
@Pointcut("execution(* com.sb.index.dao..*.*(..))")
public void pointCut_() {}
// 前置通知 : 在执行目标方法之前执行
@Before("pointCut_()")
public void begin(JoinPoint point) {
// 获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
Class<?> target = point.getTarget().getClass();
MethodSignature signature = (MethodSignature) point.getSignature();
// 默认使用目标类型的注解,如果没有则使用其实现接口的注解
for (Class<?> clazz : target.getInterfaces()) {
resolveDataSource(clazz, signature.getMethod());
}
resolveDataSource(target, signature.getMethod());
}
// 后置/最终通知:在执行目标方法之后执行 【无论是否出现异常最终都会执行】
@After("pointCut_()")
public void after(JoinPoint point) {
DataSourceContextHolder.clearDB();
logger.debug("切换默认数据源成功");
}
/**
* 提取目标对象方法注解和类型注解中的数据源标识
*
* @param clazz
* @param method
*/
private void resolveDataSource(Class<?> clazz, Method method)
{
// 设置数据源
try {
Class<?>[] types = method.getParameterTypes();
DataSource source = null;
// 默认使用类型注解
if (clazz.isAnnotationPresent(DataSource.class)) {
source = clazz.getAnnotation(DataSource.class);
DataSourceContextHolder.setDB(source.value());
}
// 方法注解可以覆盖类型注解
Method m = clazz.getMethod(method.getName(), types);
if (m != null && m.isAnnotationPresent(DataSource.class)) {
source = m.getAnnotation(DataSource.class);
DataSourceContextHolder.setDB(source.value());
}
logger.debug("设置数据源:"+source.value());
} catch (Exception e) {
logger.error(clazz + ":" + e.getMessage());
}
}
}
6、具体使用
默认主数据源未db,在需要访问第二个数据源时,在对的dao上加上@DataSource("db2")注解,即可完成数据源切换。