SpEl 实现自定义日志记录

Java有货

共 3699字,需浏览 8分钟

 ·

2021-07-29 04:23

导语

在前面我们介绍了SpEl(Spring Expression Language)解析Spring SpEl高级语法,但是SpEl在时间的开发中能帮助我们做些什么呢?该如何与自己的业务进行匹配呢?本讲将介绍一种使用方式,Aop + SpEl实现日志记录!主要是通过SpEl实现自定义的记录.Aop大家应该都很熟悉,这里不做过多介绍,如果不是很了解,可以先阅读Spring Aop 核心概念 ,下面我将进行核心的业务开发。

自定义注解



我们将自定义一个注解,用与拦截

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface DemoLog {
String name() default "demo";
String el();}

Aop 实现


这里我们采用@Around的方式,在方法前进行监听,与发生异常时进行监听

@Slf4j@Aspect@Componentpublic class LogAspect {
@Pointcut(value = "@annotation(DemoLog)") public void logAspect() {
}
/** * 环绕处理 * * @param joinPoint * @throws Throwable */ @Around(value = "logAspect()") public Object getAroundLog(ProceedingJoinPoint joinPoint) throws Throwable { Object proceed; try { //前置处理 saveLogAspect(joinPoint, null); proceed = joinPoint.proceed(); return proceed; } catch (Throwable throwable) { saveLogAspect(joinPoint, throwable); throw new RuntimeException(throwable.getMessage()); } }

private void saveLogAspect(JoinPoint joinPoint, Throwable throwable) { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); try { // 获取自定义注解 DemoLog demoLog = methodSignature.getMethod().getAnnotation(DemoLog.class); if (Objects.nonNull(demoLog)) { Object spEl = AspectExpress.getSpEl(joinPoint, methodSignature, demoLog.el(), Object.class); if (log.isInfoEnabled()) { log.info(" SpelLog {}", spEl); } } } catch (Exception e) { log.error(e.getMessage()); } }
}

自定义 SpEl解析器


我们通过自定义SpEL解析的方式实现

public class AspectExpress {

public static <T> T getSpEl(JoinPoint joinPoint, MethodSignature methodSignature, String el, Class<T> clazz){ EvaluationContext context = getContext(joinPoint.getArgs(), methodSignature.getMethod()); return getValue(context, el, clazz); }
/** * 获取spel 定义的参数值 * * @param context 参数容器 * @param key key * @param clazz 需要返回的类型 * @param <T> 返回泛型 * @return 参数值 */ private static <T> T getValue(EvaluationContext context, String key, Class<T> clazz) { SpelExpressionParser spelExpressionParser = new SpelExpressionParser(); Expression expression = spelExpressionParser.parseExpression(key); return expression.getValue(context, clazz); }

/** * 获取参数容器 * * @param arguments 方法的参数列表 * @param signatureMethod 被执行的方法体 * @return 装载参数的容器 */ private static EvaluationContext getContext(Object[] arguments, Method signatureMethod) { String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(signatureMethod); if (parameterNames == null) { throw new RuntimeException("参数列表不能为null"); } EvaluationContext context = new StandardEvaluationContext(); for (int i = 0; i < arguments.length; i++) { context.setVariable(parameterNames[i], arguments[i]); } return context; }
}

使用方式



@RestControllerpublic class SpElDemo {
@DemoLog(el = "#id") @GetMapping(value = "spel/demo/{id}") public void get(@PathVariable("id") Integer id){
}
@DemoLog(el = "#user.name") @GetMapping(value = "spel/demo") public void get(SecurityProperties.User user){
}}
最终效果

加上以SpEl的功能可以让我们的Aop操作更加强大。也可以实现更多的处理,可以是我们的日志更加丰富


添加小编微信:372787553,备注:进群 
 带您进入Java技术交流群


浏览 44
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报