Skip to content

Commit

Permalink
Merge pull request #7 from stick-i/dev
Browse files Browse the repository at this point in the history
perf: 优化执行器和表达式解析器,增加缓存
  • Loading branch information
stick-i authored May 13, 2024
2 parents 200b8e3 + 5687768 commit edf4648
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 18 deletions.
53 changes: 36 additions & 17 deletions src/main/java/cn/sticki/validator/spel/SpelValidExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,24 +87,43 @@ private static void validateField(
@NotNull Set<Object> validGroups,
@NotNull List<FieldValidResult> validationResults
) {
// 获取字段上的注解 todo 缓存
Annotation[] annotations = verifiedField.getAnnotations();
for (Annotation originalAnno : annotations) {
String annoName = originalAnno.annotationType().getName();
if (annoName.endsWith("$List") || annoName.endsWith("Container")) {
// 容器注解,需要获取容器内部的注解类型,其声明类为真实的注解类
Class<?> clazz = originalAnno.annotationType().getDeclaringClass();
//noinspection unchecked
Annotation[] originalAnnoArray = verifiedField.getAnnotationsByType((Class<Annotation>) clazz);
for (Annotation anno : originalAnnoArray) {
// 执行验证
validateFieldAnnotation(anno, verifiedObject, verifiedField, validationResults, validGroups);
// 获取字段上的注解
List<Annotation> annotations = getFieldAnnotations(verifiedField);
for (Annotation annotation : annotations) {
validateFieldAnnotation(annotation, verifiedObject, verifiedField, validationResults, validGroups);
}
}

/**
* 字段注解缓存
*/
private static final ConcurrentHashMap<Field, List<Annotation>> FIELD_ANNOTATION_CACHE = new ConcurrentHashMap<>();

/**
* 获取字段上的注解
*
* @param field 字段
* @return 注解列表
*/
private static List<Annotation> getFieldAnnotations(Field field) {
return FIELD_ANNOTATION_CACHE.computeIfAbsent(field, f -> {
Annotation[] annotations = f.getAnnotations();
List<Annotation> tempList = new ArrayList<>();

for (Annotation originalAnno : annotations) {
String annoName = originalAnno.annotationType().getName();
if (annoName.endsWith("$List") || annoName.endsWith("Container")) {
// 容器注解,需要获取容器内部的注解类型,其声明类为真实的注解类
Class<?> clazz = originalAnno.annotationType().getDeclaringClass();
//noinspection unchecked
Annotation[] originalAnnoArray = f.getAnnotationsByType((Class<Annotation>) clazz);
tempList.addAll(Arrays.asList(originalAnnoArray));
} else {
tempList.add(originalAnno);
}
} else {
// 执行验证
validateFieldAnnotation(originalAnno, verifiedObject, verifiedField, validationResults, validGroups);
}
}
return Collections.unmodifiableList(tempList);
});
}

/**
Expand All @@ -124,7 +143,7 @@ private static void validateFieldAnnotation(
@NotNull Set<Object> validateGroups
) {
Class<? extends Annotation> annoClazz = annotation.annotationType();
// 验证注解的合法性
// 验证注解的合法性 todo 这里应该可以放到获取注解的时候进行校验
if (!isSpelConstraintAnnotationCached(annoClazz)) {
return;
}
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/cn/sticki/validator/spel/parse/SpelParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* Spel表达式解析工具
*
Expand All @@ -34,6 +38,11 @@ public class SpelParser {
}
}

/**
* 表达式缓存
*/
private static final Map<String, Expression> expressionCache = new ConcurrentHashMap<>();

/**
* 解析表达式
*
Expand All @@ -44,7 +53,8 @@ public class SpelParser {
public static Object parse(String expression, Object rootObject) {
try {
log.debug("======> Parse expression [{}]", expression);
Object value = parser.parseExpression(expression).getValue(context, rootObject, Object.class);
Expression parsed = expressionCache.computeIfAbsent(expression, parser::parseExpression);
Object value = parsed.getValue(context, rootObject, Object.class);
log.debug("======> Parse result [{}]", value);
return value;
} catch (Exception e) {
Expand Down

0 comments on commit edf4648

Please sign in to comment.