Pre Merge pull request !352 from 摸摸鼻子/master

pull/352/MERGE
摸摸鼻子 2025-02-27 02:57:19 +00:00 committed by Gitee
commit 201576b5a1
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
5 changed files with 121 additions and 2 deletions

View File

@ -25,4 +25,10 @@ public @interface DataSource
*
*/
public DataSourceType value() default DataSourceType.MASTER;
/**
* el
* example: elValue="#field" () "#pojo.field" ()
*/
String elValue() default "";
}

View File

@ -1,5 +1,9 @@
package com.ruoyi.common.enums;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
/**
*
*
@ -15,5 +19,16 @@ public enum DataSourceType
/**
*
*/
SLAVE
SLAVE;
private static final Set<String> DATA_SOURCE_TYPE_SET;
static {
DATA_SOURCE_TYPE_SET = Arrays.stream(DataSourceType.values())
.map(DataSourceType::name).collect(Collectors.toSet());
}
public static boolean contains(String sourceType){
return DATA_SOURCE_TYPE_SET.contains(sourceType);
}
}

View File

@ -0,0 +1,51 @@
package com.ruoyi.common.utils.el;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.context.expression.CachedExpressionEvaluator;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author : mudi
* @date : Created in 2021/12/3 21:02
* @description :
* @modified By :
*/
public class ExpressionEvaluator<T> extends CachedExpressionEvaluator {
private final ParameterNameDiscoverer paramNameDiscoverer = new DefaultParameterNameDiscoverer();
private final Map<ExpressionKey, Expression> conditionCache = new ConcurrentHashMap<>(64);
private final Map<AnnotatedElementKey, Method> targetMethodCache = new ConcurrentHashMap<>(64);
public EvaluationContext createEvaluationContext(Object object, Class<?> targetClass, Method method, Object[] args) {
Method targetMethod = getTargetMethod(targetClass, method);
ExpressionRootObject root = new ExpressionRootObject(object, args);
return new MethodBasedEvaluationContext(root, targetMethod, args, this.paramNameDiscoverer);
}
public T condition(String conditionExpression, AnnotatedElementKey elementKey, EvaluationContext evalContext, Class<T> clazz) {
return getExpression(this.conditionCache, elementKey, conditionExpression).getValue(evalContext, clazz);
}
private Method getTargetMethod(Class<?> targetClass, Method method) {
AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
Method targetMethod = this.targetMethodCache.get(methodKey);
if (targetMethod == null) {
targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
if (targetMethod == null) {
targetMethod = method;
}
this.targetMethodCache.put(methodKey, targetMethod);
}
return targetMethod;
}
}

View File

@ -0,0 +1,25 @@
package com.ruoyi.common.utils.el;
/**
* @author : mudi
* @date : Created in 2021/12/3 21:03
* @description :
* @modified By :
*/
public class ExpressionRootObject {
private final Object object;
private final Object[] args;
public ExpressionRootObject(Object object, Object[] args) {
this.object = object;
this.args = args;
}
public Object getObject() {
return object;
}
public Object[] getArgs() {
return args;
}
}

View File

@ -1,6 +1,10 @@
package com.ruoyi.framework.aspectj;
import java.util.Objects;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.el.ExpressionEvaluator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@ -8,8 +12,10 @@ import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.expression.EvaluationContext;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.config.datasource.DynamicDataSourceContextHolder;
@ -27,6 +33,8 @@ public class DataSourceAspect
{
protected Logger logger = LoggerFactory.getLogger(getClass());
private ExpressionEvaluator<String> evaluator = new ExpressionEvaluator<>();
@Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
+ "|| @within(com.ruoyi.common.annotation.DataSource)")
public void dsPointCut()
@ -34,6 +42,18 @@ public class DataSourceAspect
}
private String getValueByEl(DataSource dataSource, JoinPoint joinPoint)
{
if (Objects.equals(dataSource.elValue(), ""))
{
return null;
}
EvaluationContext evaluationContext = evaluator.createEvaluationContext(joinPoint.getTarget(), joinPoint.getTarget().getClass(), ((MethodSignature) joinPoint.getSignature()).getMethod(), joinPoint.getArgs());
AnnotatedElementKey methodKey = new AnnotatedElementKey(((MethodSignature) joinPoint.getSignature()).getMethod(), joinPoint.getTarget().getClass());
return evaluator.condition(dataSource.elValue(), methodKey, evaluationContext, String.class);
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable
{
@ -41,7 +61,9 @@ public class DataSourceAspect
if (StringUtils.isNotNull(dataSource))
{
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
String elValue = getValueByEl(dataSource, point);
String value = DataSourceType.contains(elValue) ? elValue : dataSource.value().name();
DynamicDataSourceContextHolder.setDataSourceType(value);
}
try