package com.vincent.rsf.openApi.common.datasource; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.aop.support.AopUtils; import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.ClassUtils; import java.lang.reflect.Method; /** * 注解数据源切换 */ @Aspect @Component @Order(Ordered.HIGHEST_PRECEDENCE + 20) public class UseDataSourceAspect { @Around("@annotation(com.vincent.rsf.openApi.common.datasource.UseDataSource) || @within(com.vincent.rsf.openApi.common.datasource.UseDataSource)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { UseDataSource useDataSource = resolveAnnotation(joinPoint); if (useDataSource == null) { return joinPoint.proceed(); } DataSourceContextHolder.push(useDataSource.value()); try { return joinPoint.proceed(); } finally { DataSourceContextHolder.poll(); } } private UseDataSource resolveAnnotation(ProceedingJoinPoint joinPoint) { Object target = joinPoint.getTarget(); Class userClass = ClassUtils.getUserClass(target); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Method specific = AopUtils.getMostSpecificMethod(method, userClass); UseDataSource onMethod = AnnotationUtils.findAnnotation(specific, UseDataSource.class); if (onMethod != null) { return onMethod; } return AnnotationUtils.findAnnotation(userClass, UseDataSource.class); } }