Spring Aop中解析spel表达式,实现更灵活的功能

栏目: Java · 发布时间: 6年前

内容简介:在Spring Aop中,我们可以拿到拦截方法的参数,如果能结合spel表达式,就能实现更加灵活的功能。典型的实现有Spring的缓存注解:本文介绍如何在aop编程中解析spel表达式,提供几个通用的方法。Spring使用自定义注解实现aop的方式这里就不赘述,只着重介绍如何解析spel。

在Spring Aop中,我们可以拿到拦截方法的参数,如果能结合spel表达式,就能实现更加灵活的功能。典型的实现有Spring的缓存注解:

@Cacheable(value = "user", key = "#id", condition = "#id lt 10")
public User conditionFindById(final Long id){
}
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#user.email")
})
public User save(User user){

本文介绍如何在aop编程中解析spel表达式,提供几个通用的方法。

Spring使用自定义注解实现aop的方式这里就不赘述,只着重介绍如何解析spel。

准备

实现非常简单,Spring本身就提供了简便的api,我们只需要获取:

Method method
Object[] arguments
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表达式,首先在aop类中定义两个属性:

private ExpressionParser parser = new SpelExpressionParser();

private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();

根据spel表达式解析参数,得到结果:

/**
* 解析 spel 表达式
*
*@parammethod 方法
*@paramarguments 参数
*@paramspel 表达式
*@paramclazz 返回结果的类型
*@paramdefaultResult 默认结果
*@return执行spel表达式后的结果
*/
private <T> TparseSpel(Method method, Object[] arguments, String spel, Class<T> clazz, T defaultResult){
    String[] params = discoverer.getParameterNames(method);
    EvaluationContext context = new StandardEvaluationContext();
    for (int len = 0; len < params.length; len++) {
        context.setVariable(params[len], arguments[len]);
    }
    try {
        Expression expression = parser.parseExpression(spel);
        return expression.getValue(context, clazz);
    } catch (Exception e) {
        return defaultResult;
    }
}

总结

上述就是整个解析spel表达式的关键流程,整体来看,aop类的结构是这样的:

@Aspect
public class SpelAspect{

    private ExpressionParser parser = new SpelExpressionParser();
    private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
    
    @Around(value = "@annotation(自定义注解)")
    public Object test(ProceedingJoinPoint point)throws Throwable {
        Object obj;
        // 获取方法参数值
        Object[] arguments = point.getArgs();
        // 获取方法
        Method method = getMethod(point);
        // 从注解中获取spel字符串,省略...
        String spel = ...
        // 解析spel表达式
        Boolean result = parseSpel(method, arguments, spel, Boolean.class, Boolean.FALSE);
        // 业务操作,省略...
        ...
        return point.proceed();
    }
}

以上提供一个基本思路和几个通用的方法( #getMethod#parseSpel ),接下来就是大家发挥想象力的时间啦!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深度探索C++对象模型

深度探索C++对象模型

斯坦利•B.李普曼 (Stanley B. Lippman) / 侯捷 / 电子工业出版社 / 2012-1 / 69.00元

作者Lippman参与设计了全世界第一套C++编译程序cfront,这本书就是一位伟大的C++编译程序设计者向你阐述他如何处理各种explicit(明确出现于C++程序代码中)和implicit(隐藏于程序代码背后)的C++语意。 本书专注于C++面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承。这本书让你知道:一旦你能够了解底层实现模......一起来看看 《深度探索C++对象模型》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

SHA 加密
SHA 加密

SHA 加密工具

html转js在线工具
html转js在线工具

html转js在线工具