解析SPEL

/**
 * SPEL的正则规则
 */
private static final Pattern pattern = Pattern.compile("\\#\\{([^\\}]*)\\}");
/**
 * 方法参数解析器
 */
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

        pattern:定义了一个正则表达式,用于匹配 SPEL 表达式。SPEL 表达式的格式为 #{...},例如 #{user.id}。
        parameterNameDiscoverer:这是一个参数名称解析器,用于获取方法参数的名称。通过 DefaultParameterNameDiscoverer,可以从字节码中解析出方法参数的名称

private Method resolveMethod(ProceedingJoinPoint pjp) {
    MethodSignature signature = (MethodSignature)pjp.getSignature();
    Class<?> clazz = pjp.getTarget().getClass();
    String name = signature.getName();
    Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
    return tryGetDeclaredMethod(clazz, name, parameterTypes);
}

通过反射获取当前切入点对应的方法对象。
        获取方法签名(MethodSignature)。
        获取目标类(clazz)和方法名称(name)。
        获取方法参数类型列表(parameterTypes)。
        调用 tryGetDeclaredMethod 方法,尝试从当前类或父类中找到对应的方法

private Method tryGetDeclaredMethod(Class<?> clazz, String name, Class<?> ... parameterTypes){
    try {
        return clazz.getDeclaredMethod(name, parameterTypes);
    } catch (NoSuchMethodException e) {
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null) {
            return tryGetDeclaredMethod(superClass, name, parameterTypes);
        }
    }
    return null;
}

递归地从当前类及其父类中查找指定的方法。

        尝试通过 clazz.getDeclaredMethod 获取方法。
        如果抛出 NoSuchMethodException,检查是否有父类。
        如果有父类,递归调用 tryGetDeclaredMethod 在父类中查找。
        如果没有找到方法,返回 null。

private String getLockName(String name, ProceedingJoinPoint pjp) {
    // 1. 判断是否存在 SPEL 表达式
    if (StringUtils.isBlank(name) || !name.contains("#")) {
        return name;
    }
    // 2. 构建上下文环境
    EvaluationContext context = new MethodBasedEvaluationContext(
            TypedValue.NULL, resolveMethod(pjp), pjp.getArgs(), parameterNameDiscoverer);
    // 3. 构建 SPEL 解析器
    ExpressionParser parser = new SpelExpressionParser();
    // 4. 循环处理表达式
    Matcher matcher = pattern.matcher(name);
    while (matcher.find()) {
        String tmp = matcher.group(); // 完整的表达式(如 #{user.id})
        String group = matcher.group(1); // 表达式内容(如 user.id)
        Expression expression = parser.parseExpression(group.charAt(0) == 'T' ? group : "#" + group);
        Object value = expression.getValue(context); // 解析表达式值
        name = name.replace(tmp, ObjectUtils.nullSafeToString(value)); // 替换锁名称中的表达式
    }
    return name;
}

该方法的主要功能是解析锁名称中的 SPEL 表达式,并将其替换为实际的值。

判断是否包含 SPEL 表达式
        如果锁名称为空或不包含 #,直接返回原始名称。
构建上下文环境
        使用 MethodBasedEvaluationContext 构建一个上下文环境,供 SPEL 表达式解析时使用。
        上下文包括:
                方法签名(resolveMethod(pjp))。
                方法参数列表(pjp.getArgs())。
                参数名称解析器(parameterNameDiscoverer)。
构建 SPEL 解析器
        使用 SpelExpressionParser 创建一个解析器,用于解析 SPEL 表达式。
循环处理表达式
        使用正则表达式匹配所有 SPEL 表达式(如 #{user.id})。
        对每个表达式进行解析:
        如果表达式以 T 开头(表示静态方法调用),直接解析。
        否则,添加 # 前缀后解析。
        将解析后的值替换到锁名称中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值