本文介绍如何在aop编程中解析spel表达式,实现非常简单,Spring本身就提供了简便的api,我们只需要获取:
方法:Method method
方法参数:Object[] arguments
spel表达式:String spel
这些都能从aop入口方法的参数ProceedingJoinPoint中得到。
spel表达式显然就是从自定义注解中获取了,而获取方法和参数的方式如下:
获取方法:
private Method getMethod(ProceedingJoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
if (method.getDeclaringClass().isInterface()) {
try {
method = joinPoint
.getTarget()
.getClass()
.getDeclaredMethod(joinPoint.getSignature().getName(),
method.getParameterTypes());
} catch (SecurityException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
return method;
}
获取方法参数值:
Object[] arguments = joinPoint.getArgs();
解析:根据spel表达式解析参数,得到结果:
public class SpelUtil {
static final String SPEL_MARK = "#";
public static String parse(String spel, Method method, Object[] args) {
if (StringUtils.isEmpty(spel)) {
return "";
}
if (!spel.contains(SPEL_MARK)) {
return spel;
}
//获取被拦截方法参数名列表(使用Spring支持类库)
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paraNameArr = u.getParameterNames(method);
//使用SPEL进行key的解析
ExpressionParser parser = new SpelExpressionParser();
//SPEL上下文
StandardEvaluationContext context = new StandardEvaluationContext();
//把方法参数放入SPEL上下文中
for (int i = 0; i < paraNameArr.length; i++) {
context.setVariable(paraNameArr[i], args[i]);
}
return parser.parseExpression(spel).getValue(context, String.class);
}
}
在@AfterReturning后置方法中,按照同样的原理,也可以解析注解表达式中的出参。另外,也可以通过JSONPath.eval();解析出入参。(返回值是list也可以解析,每个对象的属性)
private void replaceMasking(Object resultObj, MaskingField maskingField) {
try {
String path = maskingField.value();
if (path.contains("$index$")) {
String listPath = path.substring(0, path.indexOf("["));
Object obj = JSONPath.eval(resultObj, listPath);
if (obj != null && obj instanceof List) {
List list = (List)obj;
List<String> originList = Lists.newArrayList();
for (int i = 0; i < list.size(); i++) {
String newPath = path.replace(INDEX_PLACEHOLDER, String.valueOf(i));
Object tmpObj = JSONPath.eval(resultObj, newPath);
String original = String.valueOf(tmpObj == null ? "" : tmpObj);
originList.add(original);
}
}
} else {
Object obj = JSONPath.eval(resultObj, path);
}
} catch (Exception e) {
log.error("something wrong when masking", e);
}
}
@MaskingField(value = "$.body.data.list[$index$].contactPhone", type = "Mobile phone number")
@MaskingField(value = "$.body.data.contactPhone", type = "Mobile phone number")