diff --git a/README.md b/README.md
index 4c7dfec..40eea22 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
> 参考 [mzt-biz-log](https://github.com/mouzt/mzt-biz-log) 实现的一款基于 spring aop 操作日志记录工具 支持自定义方法处理
-
+
diff --git a/operation-log/pom.xml b/operation-log-core/pom.xml
similarity index 86%
rename from operation-log/pom.xml
rename to operation-log-core/pom.xml
index a8484cf..9053f19 100644
--- a/operation-log/pom.xml
+++ b/operation-log-core/pom.xml
@@ -2,22 +2,24 @@
+ 4.0.0
operation-log-parent
cn.hangsman.operationlog
1.0.0
- 4.0.0
-
- operation-log
+ operation-log-core
1.0.0
-
org.springframework
spring-context-support
+
+ org.springframework
+ spring-aop
+
org.slf4j
slf4j-api
@@ -34,5 +36,4 @@
-
\ No newline at end of file
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/OperationLog.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/OperationLog.java
similarity index 91%
rename from operation-log/src/main/java/cn/hangsman/operationlog/OperationLog.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/OperationLog.java
index f26e84e..d8eae7f 100644
--- a/operation-log/src/main/java/cn/hangsman/operationlog/OperationLog.java
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/OperationLog.java
@@ -20,6 +20,6 @@ public class OperationLog {
private String fail;
private String detail;
private String category;
- private Date operatingTime;
+ private Date operationTime;
}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/Operator.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/Operator.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/Operator.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/Operator.java
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/annotation/OperationLog.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/annotation/OperationLog.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/annotation/OperationLog.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/annotation/OperationLog.java
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/annotation/OperationLogAnnotationParser.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/annotation/OperationLogAnnotationParser.java
similarity index 54%
rename from operation-log/src/main/java/cn/hangsman/operationlog/annotation/OperationLogAnnotationParser.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/annotation/OperationLogAnnotationParser.java
index b4cb84b..c937ae6 100644
--- a/operation-log/src/main/java/cn/hangsman/operationlog/annotation/OperationLogAnnotationParser.java
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/annotation/OperationLogAnnotationParser.java
@@ -2,10 +2,13 @@
import cn.hangsman.operationlog.interceptor.OperationLogParam;
import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.util.StringUtils;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -34,14 +37,25 @@ private Collection parseAnnotations(AnnotatedElement ae, bool
if (ans.isEmpty()) {
return null;
}
- return ans.stream().map(an -> OperationLogParam.builder()
- .name(ae.toString())
- .content(an.content())
- .fail(an.fail())
- .category(an.category())
- .detail(an.detail())
- .condition(an.condition())
- .before(an.before()).build()).collect(Collectors.toCollection(ArrayList::new));
+ return ans.stream().map(an -> {
+ Map beforeHandles = new HashMap<>();
+ for (String template : an.before()) {
+ if (StringUtils.hasText(template)) {
+ int delimiterIndex = template.indexOf("=");
+ String variableName = template.substring(0, delimiterIndex);
+ String expressionStr = template.substring(delimiterIndex + 1);
+ beforeHandles.put(variableName, expressionStr);
+ }
+ }
+ return OperationLogParam.builder()
+ .name(ae.toString())
+ .content(an.content())
+ .fail(an.fail())
+ .category(an.category())
+ .detail(an.detail())
+ .condition(an.condition())
+ .before(beforeHandles).build();
+ }).collect(Collectors.toCollection(ArrayList::new));
}
}
diff --git a/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/CachedExpressionEvaluator.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/CachedExpressionEvaluator.java
new file mode 100644
index 0000000..efcaba4
--- /dev/null
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/CachedExpressionEvaluator.java
@@ -0,0 +1,137 @@
+package cn.hangsman.operationlog.expression;
+
+import org.springframework.context.expression.AnnotatedElementKey;
+import org.springframework.core.DefaultParameterNameDiscoverer;
+import org.springframework.core.ParameterNameDiscoverer;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.common.TemplateAwareExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.lang.Nullable;
+import org.springframework.util.Assert;
+import org.springframework.util.ObjectUtils;
+
+import java.util.Map;
+
+/**
+ * Shared utility class used to evaluate and cache SpEL expressions that
+ * are defined on {@link java.lang.reflect.AnnotatedElement}.
+ *
+ * @author Stephane Nicoll
+ * @see AnnotatedElementKey
+ * @since 4.2
+ */
+public class CachedExpressionEvaluator {
+
+ private final ExpressionParser parser;
+
+ private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
+
+
+ /**
+ * Create a new instance with the specified {@link ExpressionParser}.
+ */
+ protected CachedExpressionEvaluator(ExpressionParser parser) {
+ Assert.notNull(parser, "SpelExpressionParser must not be null");
+ this.parser = parser;
+ }
+
+ /**
+ * Create a new instance with a default {@link SpelExpressionParser}.
+ */
+ protected CachedExpressionEvaluator() {
+ this(new SpelExpressionParser());
+ }
+
+
+ /**
+ * Return the {@link TemplateAwareExpressionParser} to use.
+ */
+ protected ExpressionParser getParser() {
+ return this.parser;
+ }
+
+ /**
+ * Return a shared parameter name discoverer which caches data internally.
+ *
+ * @since 4.3
+ */
+ protected ParameterNameDiscoverer getParameterNameDiscoverer() {
+ return this.parameterNameDiscoverer;
+ }
+
+
+ /**
+ * Return the {@link Expression} for the specified SpEL value
+ * Parse the expression if it hasn't been already.
+ *
+ * @param cache the cache to use
+ * @param elementKey the element on which the expression is defined
+ * @param expression the expression to parse
+ */
+ protected Expression getExpression(Map cache,
+ AnnotatedElementKey elementKey, String expression) {
+
+ ExpressionKey expressionKey = createKey(elementKey, expression);
+ Expression expr = cache.get(expressionKey);
+ if (expr == null) {
+ expr = getParser().parseExpression(expression);
+ cache.put(expressionKey, expr);
+ }
+ return expr;
+ }
+
+ private ExpressionKey createKey(AnnotatedElementKey elementKey, String expression) {
+ return new ExpressionKey(elementKey, expression);
+ }
+
+
+ /**
+ * An expression key.
+ */
+ protected static class ExpressionKey implements Comparable {
+
+ private final AnnotatedElementKey element;
+
+ private final String expression;
+
+ protected ExpressionKey(AnnotatedElementKey element, String expression) {
+ Assert.notNull(element, "AnnotatedElementKey must not be null");
+ Assert.notNull(expression, "Expression must not be null");
+ this.element = element;
+ this.expression = expression;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof ExpressionKey)) {
+ return false;
+ }
+ ExpressionKey otherKey = (ExpressionKey) other;
+ return (this.element.equals(otherKey.element) &&
+ ObjectUtils.nullSafeEquals(this.expression, otherKey.expression));
+ }
+
+ @Override
+ public int hashCode() {
+ return this.element.hashCode() * 29 + this.expression.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return this.element + " with expression \"" + this.expression + "\"";
+ }
+
+ @Override
+ public int compareTo(ExpressionKey other) {
+ int result = this.element.toString().compareTo(other.element.toString());
+ if (result == 0) {
+ result = this.expression.compareTo(other.expression);
+ }
+ return result;
+ }
+ }
+}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelUtil.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/ExpressionUtil.java
similarity index 98%
rename from operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelUtil.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/expression/ExpressionUtil.java
index 640f02c..c397773 100644
--- a/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelUtil.java
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/ExpressionUtil.java
@@ -1,4 +1,4 @@
-package cn.hangsman.operationlog.spel;
+package cn.hangsman.operationlog.expression;
import org.springframework.expression.ParseException;
@@ -11,7 +11,7 @@
* @author hangsman
* @since 1.0
*/
-public class SpelUtil {
+public class ExpressionUtil {
private static boolean isSuffixHere(String expressionString, int pos, String suffix) {
int suffixPosition = 0;
diff --git a/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/OperationLogExpressionEvaluator.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/OperationLogExpressionEvaluator.java
new file mode 100644
index 0000000..8bc3e3b
--- /dev/null
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/OperationLogExpressionEvaluator.java
@@ -0,0 +1,46 @@
+package cn.hangsman.operationlog.expression;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.expression.AnnotatedElementKey;
+import org.springframework.context.expression.BeanFactoryResolver;
+import org.springframework.context.expression.MethodBasedEvaluationContext;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.TypedValue;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Created by 2022/1/16 9:20
+ *
+ * @author hangsman
+ * @since 1.0
+ */
+public class OperationLogExpressionEvaluator extends CachedExpressionEvaluator {
+
+ private final Map expressionCache = new ConcurrentHashMap<>(64);
+
+ public OperationLogExpressionEvaluator(ExpressionParser parser) {
+ super(parser);
+ }
+
+ public EvaluationContext createEvaluationContext(Method method, Object[] arguments, BeanFactory beanFactory) {
+ MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(
+ TypedValue.NULL, method, arguments, getParameterNameDiscoverer());
+ if (beanFactory != null) {
+ evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
+ }
+ return evaluationContext;
+ }
+
+ public T parseExpression(String expressionStr, AnnotatedElementKey methodKey, EvaluationContext evaluationContext, Class desiredResultType) {
+ return getExpression(this.expressionCache, methodKey, expressionStr).getValue(evaluationContext, desiredResultType);
+ }
+
+ public boolean condition(String conditionExpression, AnnotatedElementKey methodKey, EvaluationContext evalContext) {
+ return (Boolean.TRUE.equals(parseExpression(conditionExpression, methodKey, evalContext, Boolean.class)));
+ }
+}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunction.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunction.java
similarity index 64%
rename from operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunction.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunction.java
index f348bdf..bea4508 100644
--- a/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunction.java
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunction.java
@@ -1,13 +1,15 @@
-package cn.hangsman.operationlog.spel;
+package cn.hangsman.operationlog.expression;
/**
- * Created by 2022/1/12 11:17
+ * Created by 2022/1/16 9:50
*
* @author hangsman
* @since 1.0
*/
public interface SpelFunction {
+
Object apply(Object value);
String functionName();
+
}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/spel/FunctionExpression.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunctionExpression.java
similarity index 94%
rename from operation-log/src/main/java/cn/hangsman/operationlog/spel/FunctionExpression.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunctionExpression.java
index c26c0c7..643851d 100644
--- a/operation-log/src/main/java/cn/hangsman/operationlog/spel/FunctionExpression.java
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunctionExpression.java
@@ -1,4 +1,4 @@
-package cn.hangsman.operationlog.spel;
+package cn.hangsman.operationlog.expression;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.EvaluationContext;
@@ -11,19 +11,19 @@
import java.util.Map;
/**
- * Created by 2022/1/12 11:47
+ * Created by 2022/1/16 9:24
*
* @author hangsman
* @since 1.0
*/
-public class FunctionExpression implements Expression {
+public class SpelFunctionExpression implements Expression {
private final String expressionStr;
private final Expression[] expressions;
private final SpelFunction function;
- public FunctionExpression(String expressionStr, Expression[] expressions,
- SpelFunction function) {
+ public SpelFunctionExpression(String expressionStr, Expression[] expressions,
+ SpelFunction function) {
this.expressionStr = expressionStr;
this.expressions = expressions;
this.function = function;
@@ -161,4 +161,5 @@ public void setValue(EvaluationContext context, Object value) throws EvaluationE
public void setValue(EvaluationContext context, Object rootObject, Object value) throws EvaluationException {
}
+
}
diff --git a/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunctionExpressionParser.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunctionExpressionParser.java
new file mode 100644
index 0000000..f6cc8d2
--- /dev/null
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/expression/SpelFunctionExpressionParser.java
@@ -0,0 +1,273 @@
+package cn.hangsman.operationlog.expression;
+
+import org.springframework.core.convert.TypeDescriptor;
+import org.springframework.expression.*;
+import org.springframework.expression.common.ExpressionUtils;
+import org.springframework.expression.common.TemplateAwareExpressionParser;
+import org.springframework.expression.common.TemplateParserContext;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * Created by 2022/1/16 9:25
+ *
+ * @author hangsman
+ * @since 1.0
+ */
+public class SpelFunctionExpressionParser extends TemplateAwareExpressionParser {
+
+ private static final Pattern VALID_FUNCTION_EXPRESSION_PATTERN = Pattern.compile(".*\\$.*?[(].*?[)].*");
+
+ private final ParserContext templateParserContext = new TemplateParserContext("{", "}");
+
+ private final ParserContext functionParserContext = new TemplateParserContext("(", ")");
+
+ private final SpelExpressionParser normalExpressionParser = new SpelExpressionParser();
+
+ private final Map functionMap = new HashMap<>();
+
+ public SpelFunctionExpressionParser(List functions) {
+ if (!CollectionUtils.isEmpty(functions)) {
+ for (SpelFunction parseFunction : functions) {
+ String functionName = parseFunction.functionName();
+ Assert.hasLength(functionName, "functionName can not be empty!");
+ functionMap.put(functionName, parseFunction);
+ }
+ }
+ }
+
+ @Override
+ public Expression parseExpression(String expressionString) throws ParseException {
+ return this.parseExpression(expressionString, templateParserContext);
+ }
+
+ @Override
+ protected Expression doParseExpression(String expressionString, ParserContext context) throws ParseException {
+ if (VALID_FUNCTION_EXPRESSION_PATTERN.matcher(expressionString).matches()) {
+ return doParseFunctionExpression(expressionString, functionParserContext);
+ }
+ return normalExpressionParser.parseExpression(expressionString);
+ }
+
+ private Expression doParseFunctionExpression(String expressionString, ParserContext context) {
+ Map variableExpressionMap = getVariableExpressionMap(expressionString, context);
+
+ String originExpressionString = expressionString;
+ // 将解析出来的方法替换成变量形式
+ // #_ret != null ? $json(#_ret) : '' 将被替换成 #_ret != null ? #fun_uuid : ''
+ for (String key : variableExpressionMap.keySet()) {
+ Expression expression = variableExpressionMap.get(key);
+ expressionString = expressionString.replace(expression.getExpressionString(), "#" + key);
+ }
+ // 然后解析上面替换好的表达式
+ Expression proxyExpression = doParseExpression(expressionString, null);
+ // ProxyExpression 会在getValue的时候先处理 variableExpressionMap 中的表达式 然后将返回值放入 EvaluationContext
+ return new ProxyExpression(originExpressionString, proxyExpression, variableExpressionMap);
+ }
+
+ /**
+ * 提取方法中的变量 然后将变量解析成表达式
+ */
+ private Map getVariableExpressionMap(String expressionString, ParserContext context) {
+ String prefix = context.getExpressionPrefix();
+ String suffix = context.getExpressionSuffix();
+ Map variableExpressionMap = new HashMap<>();
+ int startIdx = 0;
+ while (startIdx < expressionString.length()) {
+ int $Index = expressionString.indexOf("$", startIdx);
+ int prefixIndex = expressionString.indexOf(prefix, $Index);
+ if (prefixIndex >= startIdx) {
+ String functionName = expressionString.substring($Index + "$".length(), prefixIndex);
+ Assert.hasLength(functionName, "functionName can not be empty:" + expressionString);
+ int afterPrefixIndex = prefixIndex + prefix.length();
+ int suffixIndex = ExpressionUtil.skipToCorrectEndSuffix(suffix, expressionString, afterPrefixIndex);
+ if (suffixIndex == -1) {
+ throw new ParseException(expressionString, prefixIndex,
+ "No ending suffix '" + suffix + "' for expression starting at character " +
+ prefixIndex + ": " + expressionString.substring(prefixIndex));
+ }
+ if (suffixIndex == afterPrefixIndex) {
+ throw new ParseException(expressionString, prefixIndex,
+ "No expression defined within delimiter '" + prefix + suffix +
+ "' at character " + prefixIndex);
+ }
+ // 提取方法中的变量表达式
+ String expr = expressionString.substring(prefixIndex + prefix.length(), suffixIndex);
+ if (expr.isEmpty()) {
+ throw new ParseException(expressionString, prefixIndex,
+ "No expression defined within delimiter '" + prefix + suffix +
+ "' at character " + prefixIndex);
+ }
+ List expressions = new ArrayList<>();
+ // 处理变量表达式 多个变量以逗号分隔 $json(1,2,3.....)
+ for (String spel : expr.split(",")) {
+ expressions.add(doParseExpression(spel, null));
+ }
+ String functionExpressionStr = expressionString.substring($Index, suffixIndex + suffix.length());
+ SpelFunction function = getFunction(functionName);
+ Assert.notNull(function, "expression " + functionExpressionStr + " not find function :" + functionName);
+ SpelFunctionExpression functionExpression =
+ new SpelFunctionExpression(functionExpressionStr, expressions.toArray(new Expression[0]), function);
+ variableExpressionMap.put(generateVariableId(), functionExpression);
+ startIdx = suffixIndex + suffix.length();
+ } else {
+ break;
+ }
+ }
+ return variableExpressionMap;
+ }
+
+ private String generateVariableId() {
+ return "fun_" + UUID.randomUUID().toString().replace("-", "");
+ }
+
+ private SpelFunction getFunction(String functionName) {
+ return this.functionMap.get(functionName);
+ }
+
+ private static class ProxyExpression implements Expression {
+
+ private final String expressionString;
+
+ private final Expression proxyExpression;
+
+ private final Map variableExpressionMap;
+
+ public ProxyExpression(String expressionString, Expression proxyExpression, Map variableExpressionMap) {
+ this.expressionString = expressionString;
+ this.proxyExpression = proxyExpression;
+ this.variableExpressionMap = variableExpressionMap;
+ }
+
+ @Override
+ public String getExpressionString() {
+ return this.expressionString;
+ }
+
+ @Override
+ public Object getValue(EvaluationContext context) throws EvaluationException {
+ for (String key : variableExpressionMap.keySet()) {
+ Expression expression = variableExpressionMap.get(key);
+ Object value = expression.getValue(context);
+ context.setVariable(key, value);
+ }
+ return proxyExpression.getValue(context);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T getValue(EvaluationContext context, Class desiredResultType) throws EvaluationException {
+ Object result = getValue(context);
+ if (desiredResultType == null) {
+ return (T) result;
+ } else {
+ return ExpressionUtils.convertTypedValue(
+ context, new TypedValue(result), desiredResultType);
+ }
+ }
+
+ @Override
+ public Object getValue() throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public T getValue(Class desiredResultType) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public Object getValue(Object rootObject) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public T getValue(Object rootObject, Class desiredResultType) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public Object getValue(EvaluationContext context, Object rootObject) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public T getValue(EvaluationContext context, Object rootObject, Class desiredResultType) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public Class> getValueType() throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public Class> getValueType(Object rootObject) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public Class> getValueType(EvaluationContext context) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public Class> getValueType(EvaluationContext context, Object rootObject) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public TypeDescriptor getValueTypeDescriptor() throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public TypeDescriptor getValueTypeDescriptor(Object rootObject) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public TypeDescriptor getValueTypeDescriptor(EvaluationContext context, Object rootObject) throws EvaluationException {
+ return null;
+ }
+
+ @Override
+ public boolean isWritable(Object rootObject) throws EvaluationException {
+ return false;
+ }
+
+ @Override
+ public boolean isWritable(EvaluationContext context) throws EvaluationException {
+ return false;
+ }
+
+ @Override
+ public boolean isWritable(EvaluationContext context, Object rootObject) throws EvaluationException {
+ return false;
+ }
+
+ @Override
+ public void setValue(Object rootObject, Object value) throws EvaluationException {
+
+ }
+
+ @Override
+ public void setValue(EvaluationContext context, Object value) throws EvaluationException {
+
+ }
+
+ @Override
+ public void setValue(EvaluationContext context, Object rootObject, Object value) throws EvaluationException {
+
+ }
+ }
+}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/BeanFactoryOperationLogSourceAdvisor.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/BeanFactoryOperationLogSourceAdvisor.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/interceptor/BeanFactoryOperationLogSourceAdvisor.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/BeanFactoryOperationLogSourceAdvisor.java
diff --git a/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogAspectSupport.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogAspectSupport.java
new file mode 100644
index 0000000..9baf11f
--- /dev/null
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogAspectSupport.java
@@ -0,0 +1,253 @@
+package cn.hangsman.operationlog.interceptor;
+
+import cn.hangsman.operationlog.OperationLog;
+import cn.hangsman.operationlog.expression.OperationLogExpressionEvaluator;
+import cn.hangsman.operationlog.service.DefaultOperationLogRecorder;
+import cn.hangsman.operationlog.service.DefaultOperatorService;
+import cn.hangsman.operationlog.service.OperationLogRecorder;
+import cn.hangsman.operationlog.service.OperatorService;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.aop.framework.AopProxyUtils;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.*;
+import org.springframework.context.expression.AnnotatedElementKey;
+import org.springframework.core.BridgeMethodResolver;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.lang.Nullable;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Created by 2022/1/14 22:16
+ *
+ * @author hangsman
+ * @since 1.0
+ */
+@Getter
+@Setter
+public class OperationLogAspectSupport implements BeanFactoryAware, SmartInitializingSingleton {
+
+ private final Map metadataCache = new ConcurrentHashMap<>(512);
+
+ private OperatorService operatorService = new DefaultOperatorService();
+
+ private OperationLogRecorder operationLogRecorder = new DefaultOperationLogRecorder();
+
+ private OperationLogSource operationSource;
+
+ private OperationLogExpressionEvaluator evaluator;
+
+ private BeanFactory beanFactory;
+
+ protected OperationLogInvoker execute(final OperationLogInvoker invoker, Object target, Method method, Object[] args) {
+ Class> targetClass = getTargetClass(target);
+ OperationLogSource operationSource = getOperationSource();
+ Collection operations = operationSource.getLogOperations(method, targetClass);
+ if (!CollectionUtils.isEmpty(operations)) {
+ OperationLogParam operation = operations.iterator().next();
+ LogOperationContext operationContext = createLogOperationContext(operation, method, args, target, targetClass);
+ if (operationContext.isConditionPassing()) {
+ operationContext.resolveBeforeHandle();
+ boolean invokeSuccess = invoke(invoker, operationContext.evaluationContext);
+ recordLog(operationContext, invokeSuccess, new Date());
+ }
+ } else {
+ invoker.invoke();
+ }
+ return invoker;
+ }
+
+ protected boolean invoke(OperationLogInvoker invoker, EvaluationContext evaluationContext) {
+ invoker.invoke();
+ evaluationContext.setVariable("_ret", invoker.getRetValue());
+ evaluationContext.setVariable("_errorMsg", invoker.getThrowable() != null ? invoker.getThrowable().getMessage() : "");
+ return invoker.getThrowable() == null;
+ }
+
+ protected void recordLog(LogOperationContext operationContext, boolean invokeSuccess, Date operationTime) {
+ OperationLogParam operation = operationContext.metadata.operation;
+ OperationLog.OperationLogBuilder builder = OperationLog.builder();
+ builder.operator(this.operatorService.getOperator());
+ builder.operationTime(operationTime);
+ builder.category(operation.category);
+ builder.detail(operationContext.parseTemplate(operation.detail));
+ if (invokeSuccess) {
+ builder.content(operationContext.parseTemplate(operation.content));
+ } else {
+ builder.fail(operationContext.parseTemplate(operation.fail));
+ }
+ this.operationLogRecorder.record(builder.build());
+ }
+
+ private Class> getTargetClass(Object target) {
+ return AopProxyUtils.ultimateTargetClass(target);
+ }
+
+ protected LogOperationContext createLogOperationContext(
+ OperationLogParam operation, Method method, Object[] args, Object target, Class> targetClass) {
+ LogOperationMetadata metadata = getLogOperationMetadata(operation, method, targetClass);
+ return new LogOperationContext(metadata, args, target);
+ }
+
+ protected LogOperationMetadata getLogOperationMetadata(OperationLogParam operation, Method method, Class> targetClass) {
+ LogOperationCacheKey cacheKey = new LogOperationCacheKey(operation, method, targetClass);
+ LogOperationMetadata metadata = this.metadataCache.get(cacheKey);
+ if (metadata == null) {
+ metadata = new LogOperationMetadata(operation, method, targetClass);
+ this.metadataCache.put(cacheKey, metadata);
+ }
+ return metadata;
+ }
+
+ @Override
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ this.beanFactory = beanFactory;
+ }
+
+ @Override
+ public void afterSingletonsInstantiated() {
+ try {
+ setEvaluator(this.beanFactory.getBean(OperationLogExpressionEvaluator.class));
+ setOperationLogRecorder(this.beanFactory.getBean(OperationLogRecorder.class));
+ setOperatorService(this.beanFactory.getBean(OperatorService.class));
+ } catch (NoUniqueBeanDefinitionException ex) {
+ throw new IllegalStateException("no unique bean of type.", ex);
+ } catch (NoSuchBeanDefinitionException ex) {
+ throw new IllegalStateException("no bean of type found. ", ex);
+ }
+ }
+
+ protected static class LogOperationMetadata {
+
+ private final OperationLogParam operation;
+
+ private final Method method;
+
+ private final Method targetMethod;
+
+ private final AnnotatedElementKey methodKey;
+
+ public LogOperationMetadata(OperationLogParam operation, Method method, Class> targetClass) {
+ this.operation = operation;
+ this.method = BridgeMethodResolver.findBridgedMethod(method);
+ this.targetMethod = (!Proxy.isProxyClass(targetClass) ?
+ AopUtils.getMostSpecificMethod(method, targetClass) : this.method);
+ this.methodKey = new AnnotatedElementKey(this.targetMethod, targetClass);
+ }
+ }
+
+ private static final class LogOperationCacheKey implements Comparable {
+
+ private final OperationLogParam operation;
+
+ private final AnnotatedElementKey methodCacheKey;
+
+ private LogOperationCacheKey(OperationLogParam operationLogParam, Method method, Class> targetClass) {
+ this.operation = operationLogParam;
+ this.methodCacheKey = new AnnotatedElementKey(method, targetClass);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof LogOperationCacheKey)) {
+ return false;
+ }
+ LogOperationCacheKey otherKey = (LogOperationCacheKey) other;
+ return (this.operation.equals(otherKey.operation) &&
+ this.methodCacheKey.equals(otherKey.methodCacheKey));
+ }
+
+ @Override
+ public int hashCode() {
+ return (this.operation.hashCode() * 31 + this.methodCacheKey.hashCode());
+ }
+
+ @Override
+ public String toString() {
+ return this.operation + " on " + this.methodCacheKey;
+ }
+
+ @Override
+ public int compareTo(LogOperationCacheKey other) {
+ int result = this.operation.getName().compareTo(other.operation.getName());
+ if (result == 0) {
+ result = this.methodCacheKey.compareTo(other.methodCacheKey);
+ }
+ return result;
+ }
+ }
+
+ @Getter
+ protected class LogOperationContext {
+
+ private final LogOperationMetadata metadata;
+
+ private final Object[] args;
+
+ private final Object target;
+
+ private final EvaluationContext evaluationContext;
+
+ private Boolean conditionPassing;
+
+
+ public LogOperationContext(LogOperationMetadata metadata, Object[] args, Object target) {
+ this.metadata = metadata;
+ this.args = extractArgs(metadata.method, args);
+ this.target = target;
+ this.evaluationContext = createEvaluationContext(metadata.targetMethod, args);
+ }
+
+ private EvaluationContext createEvaluationContext(Method targetMethod, Object[] args) {
+ return evaluator.createEvaluationContext(targetMethod, args, beanFactory);
+ }
+
+ private Object[] extractArgs(Method method, Object[] args) {
+ if (!method.isVarArgs()) {
+ return args;
+ }
+ Object[] varArgs = ObjectUtils.toObjectArray(args[args.length - 1]);
+ Object[] combinedArgs = new Object[args.length - 1 + varArgs.length];
+ System.arraycopy(args, 0, combinedArgs, 0, args.length - 1);
+ System.arraycopy(varArgs, 0, combinedArgs, args.length - 1, varArgs.length);
+ return combinedArgs;
+ }
+
+ protected boolean isConditionPassing() {
+ if (this.conditionPassing == null) {
+ if (StringUtils.hasText(this.metadata.operation.getCondition())) {
+ this.conditionPassing = evaluator.condition(this.metadata.operation.getCondition(),
+ this.metadata.methodKey, evaluationContext);
+ } else {
+ this.conditionPassing = true;
+ }
+ }
+ return this.conditionPassing;
+ }
+
+ protected void resolveBeforeHandle() {
+ metadata.operation.before.forEach((key, value) -> {
+ Object result = evaluator.parseExpression(value, metadata.methodKey, evaluationContext, Object.class);
+ evaluationContext.setVariable(key, result);
+ });
+ }
+
+ protected String parseTemplate(String template) {
+ return evaluator.parseExpression(template, metadata.methodKey, evaluationContext, String.class);
+ }
+
+ }
+}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInterceptor.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInterceptor.java
similarity index 78%
rename from operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInterceptor.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInterceptor.java
index ddcf0e6..be76f45 100644
--- a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInterceptor.java
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInterceptor.java
@@ -19,10 +19,10 @@ public Object invoke(MethodInvocation invocation) throws Throwable {
OperationLogInvoker invoker = new OperationLogInvoker(invocation);
Object target = invocation.getThis();
Assert.state(target != null, "Target must not be null");
- try {
- return execute(invoker, target, method, invocation.getArguments());
- } catch (OperationLogInvoker.ThrowableWrapper th) {
- throw th.getOriginal();
+ invoker = execute(invoker, target, method, invocation.getArguments());
+ if (invoker.getThrowable() != null) {
+ throw invoker.getThrowable();
}
+ return invoker.getRetValue();
}
}
diff --git a/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInvoker.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInvoker.java
new file mode 100644
index 0000000..7761840
--- /dev/null
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInvoker.java
@@ -0,0 +1,31 @@
+package cn.hangsman.operationlog.interceptor;
+
+import lombok.Getter;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * Created by 2022/1/14 22:13
+ *
+ * @author hangsman
+ * @since 1.0
+ */
+@Getter
+class OperationLogInvoker {
+
+ private final MethodInvocation invocation;
+ private Object retValue;
+ private Throwable throwable;
+
+ public OperationLogInvoker(MethodInvocation invocation) {
+ this.invocation = invocation;
+ }
+
+ public void invoke() {
+ try {
+ retValue = invocation.proceed();
+ } catch (Throwable ex) {
+ throwable = ex;
+ }
+ }
+
+}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogParam.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogParam.java
similarity index 86%
rename from operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogParam.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogParam.java
index 444d680..327be2f 100644
--- a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogParam.java
+++ b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogParam.java
@@ -3,6 +3,8 @@
import lombok.Builder;
import lombok.Data;
+import java.util.Map;
+
/**
* Created by 2022/1/14 21:13
*
@@ -25,6 +27,6 @@ public class OperationLogParam {
String condition;
- String[] before;
+ Map before;
}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogSource.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogSource.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogSource.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogSource.java
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogSourcePointcut.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogSourcePointcut.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogSourcePointcut.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogSourcePointcut.java
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/service/DefaultOperationLogRecorder.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/service/DefaultOperationLogRecorder.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/service/DefaultOperationLogRecorder.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/service/DefaultOperationLogRecorder.java
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/service/DefaultOperatorService.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/service/DefaultOperatorService.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/service/DefaultOperatorService.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/service/DefaultOperatorService.java
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/service/OperationLogRecorder.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/service/OperationLogRecorder.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/service/OperationLogRecorder.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/service/OperationLogRecorder.java
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/service/OperatorService.java b/operation-log-core/src/main/java/cn/hangsman/operationlog/service/OperatorService.java
similarity index 100%
rename from operation-log/src/main/java/cn/hangsman/operationlog/service/OperatorService.java
rename to operation-log-core/src/main/java/cn/hangsman/operationlog/service/OperatorService.java
diff --git a/operation-log-spring-boot-autoconfigure/pom.xml b/operation-log-spring-boot-autoconfigure/pom.xml
index 54ee01f..534c4b5 100644
--- a/operation-log-spring-boot-autoconfigure/pom.xml
+++ b/operation-log-spring-boot-autoconfigure/pom.xml
@@ -19,12 +19,7 @@
cn.hangsman.operationlog
- operation-log
-
-
-
- org.springframework
- spring-context
+ operation-log-core
diff --git a/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/annotation/EnableOperationLog.java b/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/annotation/EnableOperationLog.java
index 9ef55cf..da0e5a8 100644
--- a/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/annotation/EnableOperationLog.java
+++ b/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/annotation/EnableOperationLog.java
@@ -3,6 +3,7 @@
import cn.hangsman.operationlog.spring.boot.autoconfigure.OperationLogAutoConfiguration;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Import;
+import org.springframework.core.Ordered;
import java.lang.annotation.*;
@@ -22,4 +23,5 @@
boolean proxyTargetClass() default false;
+ int order() default Ordered.LOWEST_PRECEDENCE;
}
diff --git a/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/autoconfigure/OperationLogAutoConfiguration.java b/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/autoconfigure/OperationLogAutoConfiguration.java
index 3272333..f16a749 100644
--- a/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/autoconfigure/OperationLogAutoConfiguration.java
+++ b/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/autoconfigure/OperationLogAutoConfiguration.java
@@ -1,9 +1,14 @@
package cn.hangsman.operationlog.spring.boot.autoconfigure;
-import cn.hangsman.operationlog.spel.SpelFunction;
-import cn.hangsman.operationlog.spel.SpelFunctionExpressionParser;
-import cn.hangsman.operationlog.spel.SpelFunctionFactory;
+import cn.hangsman.operationlog.expression.OperationLogExpressionEvaluator;
+import cn.hangsman.operationlog.expression.SpelFunction;
+import cn.hangsman.operationlog.expression.SpelFunctionExpressionParser;
+import cn.hangsman.operationlog.service.DefaultOperationLogRecorder;
+import cn.hangsman.operationlog.service.DefaultOperatorService;
+import cn.hangsman.operationlog.service.OperationLogRecorder;
+import cn.hangsman.operationlog.service.OperatorService;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -19,12 +24,24 @@
public class OperationLogAutoConfiguration {
@Bean
- SpelFunctionExpressionParser spelFunctionExpressionParser() {
- return new SpelFunctionExpressionParser();
+ public SpelFunctionExpressionParser spelFunctionExpressionParser(@Autowired(required = false) List parseFunctions) {
+ return new SpelFunctionExpressionParser(parseFunctions);
}
@Bean
- public SpelFunctionFactory spelFunctionFactory(@Autowired(required = false) List parseFunctions) {
- return new SpelFunctionFactory(parseFunctions);
+ public OperationLogExpressionEvaluator operationLogExpressionEvaluator(SpelFunctionExpressionParser expressionParser) {
+ return new OperationLogExpressionEvaluator(expressionParser);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(OperationLogRecorder.class)
+ public OperationLogRecorder operationLogRecorder() {
+ return new DefaultOperationLogRecorder();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(OperatorService.class)
+ public OperatorService operatorService() {
+ return new DefaultOperatorService();
}
}
diff --git a/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/autoconfigure/OperationLogProxyConfiguration.java b/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/autoconfigure/OperationLogProxyConfiguration.java
index 8d21543..0547013 100644
--- a/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/autoconfigure/OperationLogProxyConfiguration.java
+++ b/operation-log-spring-boot-autoconfigure/src/main/java/cn/hangsman/operationlog/spring/boot/autoconfigure/OperationLogProxyConfiguration.java
@@ -5,7 +5,6 @@
import cn.hangsman.operationlog.interceptor.OperationLogSource;
import cn.hangsman.operationlog.service.OperationLogRecorder;
import cn.hangsman.operationlog.service.OperatorService;
-import cn.hangsman.operationlog.spel.SpelFunctionExpressionParser;
import cn.hangsman.operationlog.spring.boot.annotation.EnableOperationLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -22,45 +21,35 @@
* @author hangsman
* @since 1.0
*/
-@Configuration(proxyBeanMethods = false)
+@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class OperationLogProxyConfiguration implements ImportAware {
protected AnnotationAttributes enableOperationLog;
@Bean
- public BeanFactoryOperationLogSourceAdvisor advisor(OperationLogInterceptor interceptor, OperationLogSource operationLogSource) {
+ public BeanFactoryOperationLogSourceAdvisor advisor() {
BeanFactoryOperationLogSourceAdvisor advisor = new BeanFactoryOperationLogSourceAdvisor();
- advisor.setAdvice(interceptor);
- advisor.setLogOperationSource(operationLogSource);
+ advisor.setAdvice(operationLogInterceptor());
+ advisor.setLogOperationSource(logOperationSource());
+ if (this.enableOperationLog != null) {
+ advisor.setOrder(this.enableOperationLog.getNumber("order"));
+ }
return advisor;
}
-
@Bean
- public OperationLogInterceptor operationLogInterceptor(OperationLogSource operationLogSource,
- SpelFunctionExpressionParser expressionParser,
- @Autowired(required = false) OperationLogRecorder operationLogRecorder,
- @Autowired(required = false) OperatorService operatorService) {
+ public OperationLogInterceptor operationLogInterceptor() {
OperationLogInterceptor interceptor = new OperationLogInterceptor();
- interceptor.setExpressionParser(expressionParser);
- interceptor.setOperationSource(operationLogSource);
- if (operationLogRecorder != null) {
- interceptor.setOperationLogRecorder(operationLogRecorder);
- }
- if (operatorService != null) {
- interceptor.setOperatorService(operatorService);
- }
+ interceptor.setOperationSource(logOperationSource());
return interceptor;
}
-
@Bean
public OperationLogSource logOperationSource() {
return new OperationLogSource();
}
-
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableOperationLog = AnnotationAttributes.fromMap(
diff --git a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/domain/User.java b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/domain/User.java
index ef31762..c829a79 100644
--- a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/domain/User.java
+++ b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/domain/User.java
@@ -2,7 +2,6 @@
import lombok.Builder;
import lombok.Data;
-import org.springframework.core.annotation.Order;
/**
* Created by 2022/1/14 17:23
diff --git a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/service/IUserService.java b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/service/IUserService.java
index d5cbc9c..ed99445 100644
--- a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/service/IUserService.java
+++ b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/service/IUserService.java
@@ -1,6 +1,5 @@
package cn.hangsman.operationlog.test.service;
-import cn.hangsman.operationlog.annotation.OperationLog;
import cn.hangsman.operationlog.test.domain.User;
/**
diff --git a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/service/OperationLogRecordService.java b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/service/OperationLogRecordService.java
new file mode 100644
index 0000000..1346b63
--- /dev/null
+++ b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/service/OperationLogRecordService.java
@@ -0,0 +1,26 @@
+package cn.hangsman.operationlog.test.service;
+
+import cn.hangsman.operationlog.OperationLog;
+import cn.hangsman.operationlog.service.OperationLogRecorder;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Created by 2022/1/16 15:47
+ *
+ * @author hangsman
+ * @since 1.0
+ */
+@Service
+@Slf4j
+public class OperationLogRecordService implements OperationLogRecorder {
+
+ @Autowired
+ IUserService userService;
+
+ @Override
+ public void record(OperationLog operationLog) {
+ log.info(operationLog.toString());
+ }
+}
diff --git a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/spel/JsonSpelFunction.java b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/spel/JsonSpelFunction.java
index f37b36e..59525c6 100644
--- a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/spel/JsonSpelFunction.java
+++ b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/spel/JsonSpelFunction.java
@@ -1,6 +1,7 @@
package cn.hangsman.operationlog.test.spel;
-import cn.hangsman.operationlog.spel.SpelFunction;
+
+import cn.hangsman.operationlog.expression.SpelFunction;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
diff --git a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/spel/UserNameSpelFunction.java b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/spel/UserNameSpelFunction.java
index ba9baf3..09c7b62 100644
--- a/operation-log-test/src/main/java/cn/hangsman/operationlog/test/spel/UserNameSpelFunction.java
+++ b/operation-log-test/src/main/java/cn/hangsman/operationlog/test/spel/UserNameSpelFunction.java
@@ -1,6 +1,7 @@
package cn.hangsman.operationlog.test.spel;
-import cn.hangsman.operationlog.spel.SpelFunction;
+
+import cn.hangsman.operationlog.expression.SpelFunction;
import cn.hangsman.operationlog.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
diff --git a/operation-log-test/src/test/java/cn/hangsman/operationlog/test/OperationLogTest.java b/operation-log-test/src/test/java/cn/hangsman/operationlog/test/OperationLogTest.java
index 2ab363e..69d6a35 100644
--- a/operation-log-test/src/test/java/cn/hangsman/operationlog/test/OperationLogTest.java
+++ b/operation-log-test/src/test/java/cn/hangsman/operationlog/test/OperationLogTest.java
@@ -1,6 +1,5 @@
package cn.hangsman.operationlog.test;
-import cn.hangsman.operationlog.spring.boot.annotation.EnableOperationLog;
import cn.hangsman.operationlog.test.domain.User;
import cn.hangsman.operationlog.test.service.IUserService;
import org.junit.Test;
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogAspectSupport.java b/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogAspectSupport.java
deleted file mode 100644
index 68951de..0000000
--- a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogAspectSupport.java
+++ /dev/null
@@ -1,223 +0,0 @@
-package cn.hangsman.operationlog.interceptor;
-
-import cn.hangsman.operationlog.OperationLog;
-
-import cn.hangsman.operationlog.service.DefaultOperationLogRecorder;
-import cn.hangsman.operationlog.service.DefaultOperatorService;
-import cn.hangsman.operationlog.service.OperationLogRecorder;
-import cn.hangsman.operationlog.service.OperatorService;
-import cn.hangsman.operationlog.spel.SpelFunctionExpressionParser;
-import org.springframework.aop.framework.AopProxyUtils;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.expression.AnnotatedElementKey;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.Expression;
-import org.springframework.lang.Nullable;
-import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
-
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Created by 2022/1/14 22:16
- *
- * @author hangsman
- * @since 1.0
- */
-public class OperationLogAspectSupport implements InitializingBean {
-
- private final Map metadataCache = new ConcurrentHashMap<>(512);
-
- private OperatorService operatorService = new DefaultOperatorService();
-
- private OperationLogRecorder operationLogRecorder = new DefaultOperationLogRecorder();
-
- private OperationLogSource operationSource;
-
- private SpelFunctionExpressionParser expressionParser;
-
- protected Object execute(OperationLogInvoker invoker, Object target, Method method, Object[] args) {
- Class> targetClass = getTargetClass(target);
- OperationLogSource operationSource = getOperationSource();
- Collection operations = operationSource.getLogOperations(method, targetClass);
- if (!CollectionUtils.isEmpty(operations)) {
- OperationLogParam operation = operations.iterator().next();
- EvaluationContext evaluationContext = getExpressionParser().createEvaluationContext(method, args);
- LogOperationMetadata metadata = getLogOperationMetadata(operation, method, targetClass);
- recordLog(invoker, metadata, evaluationContext);
- } else {
- invoker.invoke();
- }
- if (invoker.getThrowableWrapper() != null) {
- throw invoker.getThrowableWrapper();
- }
- return invoker.getRetValue();
- }
-
- private void recordLog(final OperationLogInvoker invoker, LogOperationMetadata metadata, EvaluationContext evaluationContext) {
- for (String variableName : metadata.variableExpressionMap.keySet()) {
- Expression expression = metadata.variableExpressionMap.get(variableName);
- evaluationContext.setVariable(variableName, expression.getValue(evaluationContext));
- }
- Date operationTime = new Date();
- invoker.invoke();
- evaluationContext.setVariable("_ret", invoker.getRetValue());
- OperationLogInvoker.ThrowableWrapper throwableWrapper = invoker.getThrowableWrapper();
- evaluationContext.setVariable("_errorMsg", throwableWrapper != null ? throwableWrapper.getMessage() : null);
- if (isConditionPassing(metadata, evaluationContext)) {
- OperationLog.OperationLogBuilder builder = OperationLog.builder();
- Map expressionMap = metadata.templateExpressionMap;
- OperationLogParam operation = metadata.operation;
- if (throwableWrapper == null) {
- builder.content(expressionMap.get(operation.content).getValue(evaluationContext, String.class));
- } else {
- builder.fail(expressionMap.get(operation.fail).getValue(evaluationContext, String.class));
- }
- builder.detail(expressionMap.get(operation.detail).getValue(evaluationContext, String.class));
- builder.operator(getOperatorService().getOperator());
- builder.operatingTime(operationTime);
- builder.category(metadata.operation.category);
- this.operationLogRecorder.record(builder.build());
- }
- }
-
-
- private boolean isConditionPassing(LogOperationMetadata metadata, EvaluationContext evaluationContext) {
- if (StringUtils.hasText(metadata.operation.condition)) {
- Expression expression = metadata.templateExpressionMap.get(metadata.operation.condition);
- Boolean expressionValue = expression.getValue(evaluationContext, Boolean.class);
- return Boolean.TRUE.equals(expressionValue);
- }
- return true;
- }
-
- private Class> getTargetClass(Object target) {
- return AopProxyUtils.ultimateTargetClass(target);
- }
-
- protected LogOperationMetadata getLogOperationMetadata(OperationLogParam operation, Method method, Class> targetClass) {
- LogOperationCacheKey cacheKey = new LogOperationCacheKey(operation, method, targetClass);
- LogOperationMetadata metadata = this.metadataCache.get(cacheKey);
- if (metadata == null) {
- Map variableExpressionMap = new HashMap<>();
- for (String template : operation.before) {
- if (StringUtils.hasText(template)) {
- int delimiterIndex = template.indexOf("=");
- String variableName = template.substring(0, delimiterIndex);
- String expressionStr = template.substring(delimiterIndex + 1);
- Expression expression = getExpressionParser().parseExpression(expressionStr);
- variableExpressionMap.put(variableName, expression);
- }
- }
- Map templateExpressionMap = new HashMap<>();
- templateExpressionMap.put(operation.content, getExpressionParser().parseExpression(operation.content));
- templateExpressionMap.put(operation.fail, getExpressionParser().parseExpression(operation.fail));
- templateExpressionMap.put(operation.detail, getExpressionParser().parseExpression(operation.detail));
- templateExpressionMap.put(operation.condition, getExpressionParser().parseExpression(operation.condition));
- metadata = new LogOperationMetadata(operation, variableExpressionMap, templateExpressionMap);
- this.metadataCache.put(cacheKey, metadata);
- }
- return metadata;
- }
-
- public OperatorService getOperatorService() {
- return operatorService;
- }
-
- public void setOperatorService(OperatorService operatorService) {
- this.operatorService = operatorService;
- }
-
- public void setOperationLogRecorder(OperationLogRecorder operationLogRecorder) {
- this.operationLogRecorder = operationLogRecorder;
- }
-
- public OperationLogSource getOperationSource() {
- return operationSource;
- }
-
- public void setOperationSource(OperationLogSource operationSource) {
- this.operationSource = operationSource;
- }
-
- public SpelFunctionExpressionParser getExpressionParser() {
- return expressionParser;
- }
-
- public void setExpressionParser(SpelFunctionExpressionParser expressionParser) {
- this.expressionParser = expressionParser;
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(expressionParser, "expressionParser can not be empty");
- Assert.notNull(operatorService, "expressionEvaluator can not be empty");
- Assert.notNull(operationLogRecorder, "OperationLogRecorder can not be empty");
- }
-
-
- protected static class LogOperationMetadata {
-
- private final OperationLogParam operation;
-
- private final Map variableExpressionMap;
-
- private final Map templateExpressionMap;
-
- public LogOperationMetadata(OperationLogParam operation, Map variableExpressionMap, Map templateExpressionMap) {
- this.operation = operation;
- this.variableExpressionMap = variableExpressionMap;
- this.templateExpressionMap = templateExpressionMap;
- }
- }
-
- private static final class LogOperationCacheKey implements Comparable {
-
- private final OperationLogParam operation;
-
- private final AnnotatedElementKey methodCacheKey;
-
- private LogOperationCacheKey(OperationLogParam operationLogParam, Method method, Class> targetClass) {
- this.operation = operationLogParam;
- this.methodCacheKey = new AnnotatedElementKey(method, targetClass);
- }
-
- @Override
- public boolean equals(@Nullable Object other) {
- if (this == other) {
- return true;
- }
- if (!(other instanceof LogOperationCacheKey)) {
- return false;
- }
- LogOperationCacheKey otherKey = (LogOperationCacheKey) other;
- return (this.operation.equals(otherKey.operation) &&
- this.methodCacheKey.equals(otherKey.methodCacheKey));
- }
-
- @Override
- public int hashCode() {
- return (this.operation.hashCode() * 31 + this.methodCacheKey.hashCode());
- }
-
- @Override
- public String toString() {
- return this.operation + " on " + this.methodCacheKey;
- }
-
- @Override
- public int compareTo(LogOperationCacheKey other) {
- int result = this.operation.getName().compareTo(other.operation.getName());
- if (result == 0) {
- result = this.methodCacheKey.compareTo(other.methodCacheKey);
- }
- return result;
- }
- }
-}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInvoker.java b/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInvoker.java
deleted file mode 100644
index 81f411b..0000000
--- a/operation-log/src/main/java/cn/hangsman/operationlog/interceptor/OperationLogInvoker.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package cn.hangsman.operationlog.interceptor;
-
-import org.aopalliance.intercept.MethodInvocation;
-
-/**
- * Created by 2022/1/14 22:13
- *
- * @author hangsman
- * @since 1.0
- */
-class OperationLogInvoker {
-
- private final MethodInvocation invocation;
- private Object retValue;
- private ThrowableWrapper throwableWrapper;
-
- public OperationLogInvoker(MethodInvocation invocation) {
- this.invocation = invocation;
- }
-
- public void invoke() throws ThrowableWrapper {
- try {
- retValue = invocation.proceed();
- } catch (Throwable ex) {
- throwableWrapper = new ThrowableWrapper(ex);
- }
- }
-
- public Object getRetValue() {
- return retValue;
- }
-
- public ThrowableWrapper getThrowableWrapper() {
- return throwableWrapper;
- }
-
- static class ThrowableWrapper extends RuntimeException {
-
- private final Throwable original;
-
- public ThrowableWrapper(Throwable original) {
- super(original.getMessage(), original);
- this.original = original;
- }
-
- public Throwable getOriginal() {
- return this.original;
- }
- }
-}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/spel/FunctionExpressionProxy.java b/operation-log/src/main/java/cn/hangsman/operationlog/spel/FunctionExpressionProxy.java
deleted file mode 100644
index 7e54882..0000000
--- a/operation-log/src/main/java/cn/hangsman/operationlog/spel/FunctionExpressionProxy.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package cn.hangsman.operationlog.spel;
-
-import org.springframework.core.convert.TypeDescriptor;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.EvaluationException;
-import org.springframework.expression.Expression;
-import org.springframework.expression.TypedValue;
-import org.springframework.expression.common.ExpressionUtils;
-
-import java.util.Map;
-
-/**
- * Created by 2022/1/12 15:42
- *
- * @author hangsman
- * @since 1.0
- */
-public class FunctionExpressionProxy implements Expression {
-
- private final String expressionString;
-
- private final Expression proxyExpression;
- private final Map variableExpressionMap;
-
- public FunctionExpressionProxy(String expressionString, Expression proxyExpression, Map variableExpressionMap) {
- this.expressionString = expressionString;
- this.proxyExpression = proxyExpression;
- this.variableExpressionMap = variableExpressionMap;
- }
-
- @Override
- public String getExpressionString() {
- return this.expressionString;
- }
-
- @Override
- public Object getValue(EvaluationContext context) throws EvaluationException {
- for (String key : variableExpressionMap.keySet()) {
- Expression expression = variableExpressionMap.get(key);
- Object value = expression.getValue(context);
- context.setVariable(key, value);
- }
- return proxyExpression.getValue(context);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public T getValue(EvaluationContext context, Class desiredResultType) throws EvaluationException {
- Object result = getValue(context);
- if (desiredResultType == null) {
- return (T) result;
- } else {
- return ExpressionUtils.convertTypedValue(
- context, new TypedValue(result), desiredResultType);
- }
- }
-
- @Override
- public Object getValue() throws EvaluationException {
- return null;
- }
-
- @Override
- public T getValue(Class desiredResultType) throws EvaluationException {
- return null;
- }
-
- @Override
- public Object getValue(Object rootObject) throws EvaluationException {
- return null;
- }
-
- @Override
- public T getValue(Object rootObject, Class desiredResultType) throws EvaluationException {
- return null;
- }
-
- @Override
- public Object getValue(EvaluationContext context, Object rootObject) throws EvaluationException {
- return null;
- }
-
- @Override
- public T getValue(EvaluationContext context, Object rootObject, Class desiredResultType) throws EvaluationException {
- return null;
- }
-
- @Override
- public Class> getValueType() throws EvaluationException {
- return null;
- }
-
- @Override
- public Class> getValueType(Object rootObject) throws EvaluationException {
- return null;
- }
-
- @Override
- public Class> getValueType(EvaluationContext context) throws EvaluationException {
- return null;
- }
-
- @Override
- public Class> getValueType(EvaluationContext context, Object rootObject) throws EvaluationException {
- return null;
- }
-
- @Override
- public TypeDescriptor getValueTypeDescriptor() throws EvaluationException {
- return null;
- }
-
- @Override
- public TypeDescriptor getValueTypeDescriptor(Object rootObject) throws EvaluationException {
- return null;
- }
-
- @Override
- public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException {
- return null;
- }
-
- @Override
- public TypeDescriptor getValueTypeDescriptor(EvaluationContext context, Object rootObject) throws EvaluationException {
- return null;
- }
-
- @Override
- public boolean isWritable(Object rootObject) throws EvaluationException {
- return false;
- }
-
- @Override
- public boolean isWritable(EvaluationContext context) throws EvaluationException {
- return false;
- }
-
- @Override
- public boolean isWritable(EvaluationContext context, Object rootObject) throws EvaluationException {
- return false;
- }
-
- @Override
- public void setValue(Object rootObject, Object value) throws EvaluationException {
-
- }
-
- @Override
- public void setValue(EvaluationContext context, Object value) throws EvaluationException {
-
- }
-
- @Override
- public void setValue(EvaluationContext context, Object rootObject, Object value) throws EvaluationException {
-
- }
-}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunctionExpressionParser.java b/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunctionExpressionParser.java
deleted file mode 100644
index b1db132..0000000
--- a/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunctionExpressionParser.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package cn.hangsman.operationlog.spel;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.*;
-import org.springframework.context.expression.BeanFactoryResolver;
-import org.springframework.context.expression.MethodBasedEvaluationContext;
-import org.springframework.core.DefaultParameterNameDiscoverer;
-import org.springframework.core.ParameterNameDiscoverer;
-import org.springframework.expression.*;
-import org.springframework.expression.common.LiteralExpression;
-import org.springframework.expression.common.TemplateAwareExpressionParser;
-import org.springframework.expression.common.TemplateParserContext;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
-import java.lang.reflect.Method;
-import java.util.*;
-
-/**
- * Created by 2022/1/12 9:58
- *
- * @author hangsman
- * @since 1.0
- */
-@Slf4j
-public class SpelFunctionExpressionParser extends TemplateAwareExpressionParser implements SmartInitializingSingleton, BeanFactoryAware {
-
- private static final String FUNCTION_VARIABLE_PREFIX = "$";
-
- private final LiteralExpression EMPTY_EXPRESSION = new LiteralExpression("");
-
- private final ParserContext functionParserContext = new TemplateParserContext("(", ")");
-
- private final ParserContext templateParserContext = new TemplateParserContext("{", "}");
-
- private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
-
- private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
-
- private SpelFunctionFactory functionFactory;
-
- private BeanFactory beanFactory;
-
- public EvaluationContext createEvaluationContext(Method method, Object[] arguments) {
- MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(
- TypedValue.NULL, method, arguments, this.parameterNameDiscoverer);
- if (beanFactory != null) {
- evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
- }
- return evaluationContext;
- }
-
- @Override
- public Expression parseExpression(String expressionString) throws ParseException {
- if (!StringUtils.hasText(expressionString)) {
- return EMPTY_EXPRESSION;
- }
- try {
- return this.parseExpression(expressionString, templateParserContext);
- } catch (Exception e) {
- log.error("parse expression error : {}", expressionString);
- throw e;
- }
- }
-
- @Override
- protected Expression doParseExpression(String expressionString, ParserContext context) throws ParseException {
- if (expressionString.contains(FUNCTION_VARIABLE_PREFIX)) {
- return doParseFunctionExpression(expressionString, functionParserContext);
- } else {
- return spelExpressionParser.parseExpression(expressionString);
- }
- }
-
- private Expression doParseFunctionExpression(String expressionString, ParserContext context) {
- String prefix = context.getExpressionPrefix();
- String suffix = context.getExpressionSuffix();
- Map variableExpressionMap = new HashMap<>();
- int startIdx = 0;
- while (startIdx < expressionString.length()) {
- int $Index = expressionString.indexOf(FUNCTION_VARIABLE_PREFIX, startIdx);
- int prefixIndex = expressionString.indexOf(prefix, $Index);
- if (prefixIndex >= startIdx) {
- String functionName = expressionString.substring($Index + FUNCTION_VARIABLE_PREFIX.length(), prefixIndex);
- Assert.hasLength(functionName, "functionName can not be empty:" + expressionString);
- int afterPrefixIndex = prefixIndex + prefix.length();
- int suffixIndex = SpelUtil.skipToCorrectEndSuffix(suffix, expressionString, afterPrefixIndex);
- if (suffixIndex == -1) {
- throw new ParseException(expressionString, prefixIndex,
- "No ending suffix '" + suffix + "' for expression starting at character " +
- prefixIndex + ": " + expressionString.substring(prefixIndex));
- }
- if (suffixIndex == afterPrefixIndex) {
- throw new ParseException(expressionString, prefixIndex,
- "No expression defined within delimiter '" + prefix + suffix +
- "' at character " + prefixIndex);
- }
- String expr = expressionString.substring(prefixIndex + prefix.length(), suffixIndex);
- if (expr.isEmpty()) {
- throw new ParseException(expressionString, prefixIndex,
- "No expression defined within delimiter '" + prefix + suffix +
- "' at character " + prefixIndex);
- }
- List expressions = new ArrayList<>();
- for (String spel : expr.split(",")) {
- expressions.add(doParseExpression(spel, null));
- }
- String expressionStr = FUNCTION_VARIABLE_PREFIX + functionName + prefix + expr + suffix;
- SpelFunction function = functionFactory.getFunction(functionName);
- Assert.notNull(function, "could not find function :" + functionName);
- FunctionExpression functionExpression = new FunctionExpression(expressionStr, expressions.toArray(new Expression[0]), function);
- String variableId = UUID.randomUUID().toString().replace("-", "");
- variableExpressionMap.put("function_" + variableId, functionExpression);
- startIdx = suffixIndex + suffix.length();
- } else {
- break;
- }
- }
- String originExpressionString = expressionString;
- for (String key : variableExpressionMap.keySet()) {
- Expression expression = variableExpressionMap.get(key);
- expressionString = expressionString.replace(expression.getExpressionString(), "#" + key);
- }
- Expression proxyExpression = doParseExpression(expressionString, null);
- return new FunctionExpressionProxy(originExpressionString, proxyExpression, variableExpressionMap);
- }
-
- @Override
- public void afterSingletonsInstantiated() {
- try {
- setFunctionFactory(this.beanFactory.getBean(SpelFunctionFactory.class));
- } catch (NoUniqueBeanDefinitionException ex) {
- throw new IllegalStateException("no unique bean of type " +
- "SpelFunctionFactory found. Mark one as primary or declare a specific SpelFunctionFactory to use.", ex);
- } catch (NoSuchBeanDefinitionException ex) {
- throw new IllegalStateException("no bean of type SpelFunctionFactory found. " +
- "Register a SpelFunctionFactory bean or remove the @EnableOperationLog annotation from your configuration.", ex);
- }
- }
-
- @Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- this.beanFactory = beanFactory;
- }
-
- public void setFunctionFactory(SpelFunctionFactory functionFactory) {
- this.functionFactory = functionFactory;
- }
-}
diff --git a/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunctionFactory.java b/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunctionFactory.java
deleted file mode 100644
index 51496a2..0000000
--- a/operation-log/src/main/java/cn/hangsman/operationlog/spel/SpelFunctionFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package cn.hangsman.operationlog.spel;
-
-import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Created by 2022/1/12 11:16
- *
- * @author hangsman
- * @since 1.0
- */
-public class SpelFunctionFactory {
-
- private final Map functionMap = new HashMap<>();
-
- public SpelFunctionFactory(List functions) {
- if (!CollectionUtils.isEmpty(functions)) {
- for (SpelFunction parseFunction : functions) {
- String functionName = parseFunction.functionName();
- Assert.hasLength(functionName, "functionName can not be empty!");
- functionMap.put(functionName, parseFunction);
- }
- }
- }
-
- public SpelFunction getFunction(String functionName) {
- return this.functionMap.get(functionName);
- }
-
-
-}
diff --git a/pom.xml b/pom.xml
index 51b82cb..31b7a58 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
operation-log-parent
1.0.0
- operation-log
+ operation-log-core
operation-log-spring-boot-autoconfigure
operation-log-spring-boot-starter
operation-log-test
@@ -67,7 +67,7 @@
cn.hangsman.operationlog
- operation-log
+ operation-log-core
1.0.0