|
|
@@ -1,113 +1,138 @@
|
|
|
-package com.storlead.framework.mybatis.datasource;//package com.storlead.framework.mybatis.datasource;
|
|
|
-//
|
|
|
-//import com.baomidou.dynamic.datasource.annotation.DS;
|
|
|
-//import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
|
|
-//import lombok.RequiredArgsConstructor;
|
|
|
-//import lombok.extern.slf4j.Slf4j;
|
|
|
-//import org.aspectj.lang.ProceedingJoinPoint;
|
|
|
-//import org.aspectj.lang.annotation.Around;
|
|
|
-//import org.aspectj.lang.annotation.Aspect;
|
|
|
-//import org.aspectj.lang.annotation.Pointcut;
|
|
|
-//import org.aspectj.lang.reflect.MethodSignature;
|
|
|
-//import org.springframework.core.annotation.AnnotatedElementUtils;
|
|
|
-//import org.springframework.core.annotation.Order;
|
|
|
-//import org.springframework.stereotype.Component;
|
|
|
-//import org.springframework.util.StringUtils;
|
|
|
-//
|
|
|
-//import java.lang.reflect.Method;
|
|
|
-//
|
|
|
-///**
|
|
|
-// * 子模块默认数据源:按配置包前缀 push 数据源;若目标已标注 {@link DS} 则跳过,由官方 {@code @DS} 切面处理。
|
|
|
-// */
|
|
|
-//@Slf4j
|
|
|
-//@Aspect
|
|
|
-//@Component
|
|
|
-//@Order(0)
|
|
|
-//@RequiredArgsConstructor
|
|
|
-//public class ModuleDefaultDataSourceAspect {
|
|
|
-//
|
|
|
-// private final ModuleDefaultDataSourceProperties properties;
|
|
|
-//
|
|
|
-// @Pointcut("execution(* *(..)) && (within(com.storlead..service..*) || within(com.storlead..mapper..*))")
|
|
|
-// public void moduleServiceOrMapperLayer() {
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Around("moduleServiceOrMapperLayer()")
|
|
|
-// public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
|
|
-// if (!properties.isModuleDefaultEnabled()) {
|
|
|
-// return joinPoint.proceed();
|
|
|
-// }
|
|
|
-// if (hasDsAnnotation(joinPoint)) {
|
|
|
-// return joinPoint.proceed();
|
|
|
-// }
|
|
|
-// String datasource = resolveDatasource(joinPoint);
|
|
|
-// if (!StringUtils.hasText(datasource)) {
|
|
|
-// return joinPoint.proceed();
|
|
|
-// }
|
|
|
-// DynamicDataSourceContextHolder.push(datasource);
|
|
|
-// try {
|
|
|
-// if (log.isDebugEnabled()) {
|
|
|
-// log.debug("module default datasource [{}] -> {}", datasource, joinPoint.getSignature().toShortString());
|
|
|
-// }
|
|
|
-// return joinPoint.proceed();
|
|
|
-// } finally {
|
|
|
-// DynamicDataSourceContextHolder.poll();
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// private boolean hasDsAnnotation(ProceedingJoinPoint joinPoint) {
|
|
|
-// MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
|
|
-// Method method = signature.getMethod();
|
|
|
-// Class<?> declaringType = signature.getDeclaringType();
|
|
|
-// if (AnnotatedElementUtils.hasAnnotation(method, DS.class)) {
|
|
|
-// return true;
|
|
|
-// }
|
|
|
-// if (declaringType != null && AnnotatedElementUtils.hasAnnotation(declaringType, DS.class)) {
|
|
|
-// return true;
|
|
|
-// }
|
|
|
-// return AnnotatedElementUtils.hasAnnotation(joinPoint.getTarget().getClass(), DS.class);
|
|
|
-// }
|
|
|
-//
|
|
|
-// /**
|
|
|
-// * 最长包前缀匹配
|
|
|
-// */
|
|
|
-// private String resolveDatasource(ProceedingJoinPoint joinPoint) {
|
|
|
-// String className = resolveBusinessClassName(joinPoint);
|
|
|
-// String matchedDs = null;
|
|
|
-// int matchedLen = -1;
|
|
|
-// for (ModuleDefaultDataSourceProperties.ModuleDefaultRule rule : properties.getModuleDefaults()) {
|
|
|
-// if (rule.getPackages() == null || !StringUtils.hasText(rule.getDatasource())) {
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// for (String pkg : rule.getPackages()) {
|
|
|
-// if (!StringUtils.hasText(pkg)) {
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// if (matchesPackage(className, pkg.trim()) && pkg.length() > matchedLen) {
|
|
|
-// matchedLen = pkg.length();
|
|
|
-// matchedDs = rule.getDatasource();
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// return matchedDs;
|
|
|
-// }
|
|
|
-//
|
|
|
-// private boolean matchesPackage(String className, String packagePrefix) {
|
|
|
-// return className.equals(packagePrefix)
|
|
|
-// || className.startsWith(packagePrefix + ".");
|
|
|
-// }
|
|
|
-//
|
|
|
-// /**
|
|
|
-// * Mapper 为 JDK 代理时,用接口全限定名匹配包前缀。
|
|
|
-// */
|
|
|
-// private String resolveBusinessClassName(ProceedingJoinPoint joinPoint) {
|
|
|
-// if (joinPoint.getSignature() instanceof MethodSignature) {
|
|
|
-// MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
|
|
-// Class<?> declaringType = signature.getDeclaringType();
|
|
|
-// if (declaringType != null && declaringType.getName().startsWith("com.storlead.")) {
|
|
|
-// return declaringType.getName();
|
|
|
-// }
|
|
|
-// }
|
|
|
-// return joinPoint.getTarget().getClass().getName();
|
|
|
-// }
|
|
|
-//}
|
|
|
+package com.storlead.framework.mybatis.datasource;
|
|
|
+
|
|
|
+import com.baomidou.dynamic.datasource.annotation.DS;
|
|
|
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.aspectj.lang.ProceedingJoinPoint;
|
|
|
+import org.aspectj.lang.annotation.Around;
|
|
|
+import org.aspectj.lang.annotation.Aspect;
|
|
|
+import org.aspectj.lang.annotation.Pointcut;
|
|
|
+import org.aspectj.lang.reflect.MethodSignature;
|
|
|
+import org.springframework.core.annotation.AnnotatedElementUtils;
|
|
|
+import org.springframework.core.annotation.Order;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+
|
|
|
+import java.lang.reflect.Method;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 子模块默认数据源:按配置包前缀 push 数据源。
|
|
|
+ * <p>
|
|
|
+ * 若目标已标注 {@link DS},由本切面直接 push 其 value(不再仅“跳过”依赖官方切面,
|
|
|
+ * 避免官方 @DS 未织入时落到 primary/master)。
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Aspect
|
|
|
+@Component
|
|
|
+@Order(0)
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class ModuleDefaultDataSourceAspect {
|
|
|
+
|
|
|
+ private final ModuleDefaultDataSourceProperties properties;
|
|
|
+
|
|
|
+ @Pointcut("execution(* *(..)) && (within(com.storlead..service..*) || within(com.storlead..mapper..*))")
|
|
|
+ public void moduleServiceOrMapperLayer() {
|
|
|
+ }
|
|
|
+
|
|
|
+ @Around("moduleServiceOrMapperLayer()")
|
|
|
+ public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
|
|
+ if (!properties.isModuleDefaultEnabled()) {
|
|
|
+ return joinPoint.proceed();
|
|
|
+ }
|
|
|
+ String datasource = resolveExplicitDs(joinPoint);
|
|
|
+ if (!StringUtils.hasText(datasource)) {
|
|
|
+ datasource = resolveDatasource(joinPoint);
|
|
|
+ }
|
|
|
+ if (!StringUtils.hasText(datasource)) {
|
|
|
+ return joinPoint.proceed();
|
|
|
+ }
|
|
|
+ DynamicDataSourceContextHolder.push(datasource);
|
|
|
+ try {
|
|
|
+ if (log.isDebugEnabled()) {
|
|
|
+ log.debug("module datasource [{}] -> {}", datasource, joinPoint.getSignature().toShortString());
|
|
|
+ }
|
|
|
+ return joinPoint.proceed();
|
|
|
+ } finally {
|
|
|
+ DynamicDataSourceContextHolder.poll();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 方法 / 声明类 / 实际目标类上的 @DS 优先
|
|
|
+ */
|
|
|
+ private String resolveExplicitDs(ProceedingJoinPoint joinPoint) {
|
|
|
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
|
|
+ Method method = signature.getMethod();
|
|
|
+ DS ds = AnnotatedElementUtils.findMergedAnnotation(method, DS.class);
|
|
|
+ if (ds != null && StringUtils.hasText(ds.value())) {
|
|
|
+ return ds.value();
|
|
|
+ }
|
|
|
+ Class<?> declaringType = signature.getDeclaringType();
|
|
|
+ if (declaringType != null) {
|
|
|
+ ds = AnnotatedElementUtils.findMergedAnnotation(declaringType, DS.class);
|
|
|
+ if (ds != null && StringUtils.hasText(ds.value())) {
|
|
|
+ return ds.value();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Class<?> targetClass = joinPoint.getTarget() != null ? joinPoint.getTarget().getClass() : null;
|
|
|
+ if (targetClass != null) {
|
|
|
+ ds = AnnotatedElementUtils.findMergedAnnotation(targetClass, DS.class);
|
|
|
+ if (ds != null && StringUtils.hasText(ds.value())) {
|
|
|
+ return ds.value();
|
|
|
+ }
|
|
|
+ // CGLIB 代理取父类
|
|
|
+ Class<?> superclass = targetClass.getSuperclass();
|
|
|
+ if (superclass != null && superclass != Object.class) {
|
|
|
+ ds = AnnotatedElementUtils.findMergedAnnotation(superclass, DS.class);
|
|
|
+ if (ds != null && StringUtils.hasText(ds.value())) {
|
|
|
+ return ds.value();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 最长包前缀匹配
|
|
|
+ */
|
|
|
+ private String resolveDatasource(ProceedingJoinPoint joinPoint) {
|
|
|
+ String className = resolveBusinessClassName(joinPoint);
|
|
|
+ String matchedDs = null;
|
|
|
+ int matchedLen = -1;
|
|
|
+ for (ModuleDefaultDataSourceProperties.ModuleDefaultRule rule : properties.getModuleDefaults()) {
|
|
|
+ if (rule.getPackages() == null || !StringUtils.hasText(rule.getDatasource())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for (String pkg : rule.getPackages()) {
|
|
|
+ if (!StringUtils.hasText(pkg)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (matchesPackage(className, pkg.trim()) && pkg.length() > matchedLen) {
|
|
|
+ matchedLen = pkg.length();
|
|
|
+ matchedDs = rule.getDatasource();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return matchedDs;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean matchesPackage(String className, String packagePrefix) {
|
|
|
+ return className.equals(packagePrefix)
|
|
|
+ || className.startsWith(packagePrefix + ".");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Mapper 为 JDK 代理时,用接口全限定名匹配包前缀。
|
|
|
+ */
|
|
|
+ private String resolveBusinessClassName(ProceedingJoinPoint joinPoint) {
|
|
|
+ if (joinPoint.getSignature() instanceof MethodSignature) {
|
|
|
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
|
|
+ Class<?> declaringType = signature.getDeclaringType();
|
|
|
+ if (declaringType != null && declaringType.getName().startsWith("com.storlead.")) {
|
|
|
+ return declaringType.getName();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return joinPoint.getTarget().getClass().getName();
|
|
|
+ }
|
|
|
+}
|