前言

在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
  • 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表达式,首先在aop类中定义两个属性:

private ExpressionParser parser = new SpelExpressionParser();private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
复制代码

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

    /*** 解析 spel 表达式** @param method    方法* @param arguments 参数* @param spel      表达式* @param clazz     返回结果的类型* @param defaultResult 默认结果* @return 执行spel表达式后的结果*/private <T> T parseSpel(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),接下来就是大家发挥想象力的时间啦!

阅读原文

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

  1. 说说如何在 Spring 框架中使用 SpEL 表达式

    在 Spring 框架的 XML 配置方式或者注解配置方式中,我们都可以使用 SpEL 表达式,它们的语法都是 #{表达式}. 1 基于 XML 配置 在 XML 配置中,我们可以通过 SpEL 表达 ...

  2. Spring AOP中pointcut expression表达式解析 及匹配多个条件

    (* com.evan.crm.service.*.*(..))中几个通配符的含义: |第一个 * -- 通配 随便率性返回值类型|  |第二个 * -- 通配包com.evan.crm.servic ...

  3. Spring AOP中pointcut expression表达式解析

    Pointcut 是指那些方法需要被执行"AOP",是由"Pointcut Expression"来描述的. Pointcut可以有下列方式来定义或者通过&am ...

  4. Spring AOP中@Pointcut切入点表达式详解

    目录 一.瞅一眼标准的AspectJ Aop的pointcut的表达式 二.SpringAop的十一种AOP表达式 三.演示使用 1.execution: 2.within: 3.this: 4.ta ...

  5. java args例子_Spring AOP中使用args表达式的方法示例

    本文实例讲述了Spring AOP中使用args表达式的方法.分享给大家供大家参考,具体如下: 一 配置 xmlns:xsi="http://www.w3.org/2001/XMLSchem ...

  6. spring aop中pointcut表达式

    spring aop中pointcut表达式 本文主要介绍spring aop中9种切入点表达式的写法 execute within this target args @target @within ...

  7. Spring AOP中的静态代理和动态代理的原理和实践

    对于最近博主最近写博客的兴致大发,我也在思考:为什么而写博客?在互联网时代,无论你是牛人大咖,还是小白菜鸟,都有发表自己看法的权利.无论你是对的还是错的,都会在这个平台上找到答案.所以,我会尽可能去写 ...

  8. Spring AOP中定义切点(PointCut)和通知(Advice)

    本文讨论一下Spring AOP编程中的两个关键问题,定义切点和定义通知,理解这两个问题能应付大部分AOP场景. 如果你还不熟悉AOP,请先看AOP基本原理,本文的例子也沿用了AOP基本原理中的例子. ...

  9. Spring AOP中定义切点PointCut详解

    1.AOP是什么? 软件工程有一个基本原则叫做"关注点分离"(Concern Separation),通俗的理解就是不同的问题交给不同的部分去解决,每部分专注于解决自己的问题.这年 ...

最新文章

  1. java oralce merge_mybatis 使用oracle merge into 语句踩坑实录(示例代码)
  2. SDCC 2015架构专场札记:一线互联网公司的架构实践
  3. Java函数式接口看这一篇就够了
  4. binaryreader java,C# 二进制文件的读写 | 菜鸟教程
  5. java猜单词游戏_序列应用——猜单词游戏
  6. liunx驱动----异步通知
  7. Ubuntu 12.10连接米2
  8. 工作资讯002---FaaS和PaaS的关系_Iaas_Paas_Saas
  9. 第四届泰迪杯数据挖掘挑战赛B题数据预处理-数据导入(Matlab)
  10. GEE植被覆盖度计算
  11. 总结 工作法(时间管理+复盘)
  12. Arcgis中修改属性字段名
  13. 服务器bmc口装系统,IBM X3650服务器BMC安装系统
  14. 导弹巡航追踪目标模拟程序(1)源码版--matlab
  15. CMD的打开方式以及一些常用的Dos命令
  16. Light OJ 1138
  17. 使用TestFlight安装ios APP的测试版本
  18. kafka的Rebalance问题分析(续)
  19. NSD Devops day03
  20. SVN图标消失解决方案

热门文章

  1. 获取 python import模块的路径
  2. oracle 创建字段自增长——两种实现方式汇总(转)
  3. 让学习体系化,造福一大波上进青年
  4. Linux进程间通信——信号
  5. 分享一些android的资料 很实用
  6. 路由器访问控制列表详解
  7. 一起等补丁:操作系统漏洞StrandHogg 2.0几乎影响所有安卓设备
  8. Java多线程设计要点
  9. Infortrend大数据时代广电行业应用
  10. 什么是BIOS?BIOS是什么