001package com.mybatisflex.spring.datasource.processor; 002 003import com.mybatisflex.core.datasource.processor.DataSourceProcessor; 004import com.mybatisflex.core.util.StringUtil; 005import org.springframework.context.expression.MethodBasedEvaluationContext; 006import org.springframework.core.DefaultParameterNameDiscoverer; 007import org.springframework.core.ParameterNameDiscoverer; 008import org.springframework.expression.BeanResolver; 009import org.springframework.expression.ExpressionParser; 010import org.springframework.expression.ParserContext; 011import org.springframework.expression.spel.standard.SpelExpressionParser; 012import org.springframework.expression.spel.support.StandardEvaluationContext; 013 014import java.lang.reflect.Method; 015 016/** 017 * SpEL表达式支持处理器 018 * 019 * @author Alay 020 * @since 2024-12-07 15:48 021 */ 022public class SpelExpressionDataSourceProcessor implements DataSourceProcessor { 023 /** 024 * 动态表达式前缀 025 */ 026 private static final String DYNAMIC_PREFIX = "#"; 027 /** 028 * 参数发现器 029 */ 030 private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); 031 /** 032 * Express语法解析器 033 */ 034 private static final ExpressionParser PARSER = new SpelExpressionParser(); 035 036 private BeanResolver beanResolver; 037 /** 038 * 解析上下文的模板 对于默认不设置的情况下,从参数中取值的方式 #param1 039 * 设置指定模板 ParserContext. TEMPLATE_EXPRESSION{@link ParserContext#TEMPLATE_EXPRESSION} 后的取值方式: #{#param1} 040 */ 041 private ParserContext parserContext = new ParserContext() { 042 043 @Override 044 public boolean isTemplate() { 045 return false; 046 } 047 048 @Override 049 public String getExpressionPrefix() { 050 return null; 051 } 052 053 @Override 054 public String getExpressionSuffix() { 055 return null; 056 } 057 }; 058 059 060 @Override 061 public String process(String dataSourceKey, Object mapper, Method method, Object[] arguments) { 062 if (StringUtil.noText(dataSourceKey)) return null; 063 if (!dataSourceKey.startsWith(DYNAMIC_PREFIX)) return null; 064 if (arguments.length == 0) return null; 065 066 RootObject rootObject = new RootObject(method, arguments, mapper); 067 StandardEvaluationContext context = new MethodBasedEvaluationContext(rootObject, method, arguments, NAME_DISCOVERER); 068 context.setBeanResolver(beanResolver); 069 final Object value = PARSER.parseExpression(dataSourceKey, parserContext).getValue(context); 070 return value == null ? null : value.toString(); 071 } 072 073 074 public void setBeanResolver(BeanResolver beanResolver) { 075 this.beanResolver = beanResolver; 076 } 077 078 public void setParserContext(ParserContext parserContext) { 079 this.parserContext = parserContext; 080 } 081 082 public static class RootObject { 083 private final Method method; 084 private final Object[] args; 085 private final Object target; 086 087 public RootObject(Method method, Object[] args, Object target) { 088 this.method = method; 089 this.args = args; 090 this.target = target; 091 } 092 093 public Method getMethod() { 094 return method; 095 } 096 097 public Object[] getArgs() { 098 return args; 099 } 100 101 public Object getTarget() { 102 return target; 103 } 104 } 105 106}