自定义注解结合切面和spel表达式
在我们的实际开发中可能存在这么一种情况,当方法参数中的某些条件成立的时候,需要执行一些逻辑处理,比如输出日志。而这些代码可能都是差不多的,那么这个时候就可以结合自定义注解加上切面加上spel表达式进行处理。就比如在spring中我们可以使用@Cacheable(key="#xx")实现缓存,这个#xx就是一个spel表达式。
需求:我们需要将service层方法中方法的某个参数的值大于0.5的方法,输出方法执行日志。(需要了解一些spel表达式的语法)
实现步骤:
1、自定义一个注解Log
2、自定义一个切面,拦截所有方法上存在@Log注解修饰的方法
3、写一个service层方法,方法上标注@Log注解
难点:
在切面中需要拿到具体执行方法的方法名,可以使用spring提供的LocalVariableTableParameterNameDiscoverer来获取到
一、自定义一个注解
注意:注解中的spel的值是必须的,且spel表达式返回的结果应该是一个布尔值
/**
* 记录日志信息,当spel表但是中的值为true时,输出日志信息
*
* @描述
* @作者 huan
* @时间 2017年10月2日 - 上午10:25:39
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String spel();
String desc() default "描述";
}
二、自定义一个service类,在需要拦截的方法上加上@Log注解
三、写一个自定义切面
注意一下解析spel表达式中context的设值即可
/**
* 日志切面,当条件满足时输出日志.
*
* @描述
* @作者 huan
* @时间 2017年10月2日 - 上午10:32:16
*/
@Component
@Aspect
public class LogAspect {
ExpressionParser parser = new SpelExpressionParser();
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
@Around("@annotation(log)")
public Object invoked(ProceedingJoinPoint pjp, Log log) throws Throwable {
Object[] args = pjp.getArgs();
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
String spel = log.spel();
String[] params = discoverer.getParameterNames(method);
EvaluationContext context = new StandardEvaluationContext();
for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]);
}
Expression expression = parser.parseExpression(spel);
if (expression.getValue(context, Boolean.class)) {
System.out.println(log.desc() + ",在" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "执行方法," + pjp.getTarget().getClass() + "." + method.getName()
+ "(" + convertArgs(args) + ")");
}
return pjp.proceed();
}
private String convertArgs(Object[] args) {
StringBuilder builder = new StringBuilder();
for (Object arg : args) {
if (null == arg) {
builder.append("null");
} else {
builder.append(arg.toString());
}
builder.append(',');
}
builder.setCharAt(builder.length() - 1, ' ');
return builder.toString();
}
}
四、pom文件的依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
五、测试。
六、增加内容:
1、当我们想在自己写的spel表达式中调用spring bean 管理的方法时,如何写。spel表达式支持使用 @来引用bean,但是此时需要注入BeanFactory
自定义注解结合切面和spel表达式的更多相关文章
- 010-Spring aop 001-核心说明-拦截指定类与方法、基于自定义注解的切面
一.概述 面向切面编程(AOP)是针对面向对象编程(OOP)的补充,可以非侵入式的为多个不具有继承关系的对象引入相同的公共行为例如日志.安全.事务.性能监控等等.SpringAOP允许将公共行为从业务 ...
- Spring自定义注解配置切面实现日志记录
一: spring-mvc.xml: <!--配置日志切面 start,必须与mvc配置在同一个配置文件,否则无法切入Controller层--><!-- 声明自动为spring容器 ...
- 使用自定义注解和切面AOP实现Java程序增强
1.注解介绍 1.1注解的本质 Oracle官方对注解的定义为: Annotations, a form of metadata, provide data about a program that ...
- 用AOP拦截自定义注解并获取注解属性与上下文参数(基于Springboot框架)
目录 自定义注解 定义切面 获取上下文信息JoinPoint ProceedingJoinPoint 定义测试方法 测试结果 小结 AOP可以用于日志的设计,这样话就少不了要获取上下文的信息,博主在设 ...
- spring boot通过自定义注解和AOP拦截指定的请求
一 准备工作 1.1 添加依赖 通过spring boot创建好工程后,添加如下依赖,不然工程中无法使用切面的注解,就无法对制定的方法进行拦截 <dependency> <group ...
- 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版
欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...
- redis缓存切面实现(支持缓存key的spel表达式)
1.定义注解 package com.g2.order.server.annotation; import java.lang.annotation.ElementType; import java. ...
- Spring Boot 自定义注解,AOP 切面统一打印出入参请求日志
其实,小哈在之前就出过一篇关于如何使用 AOP 切面统一打印请求日志的文章,那为什么还要再出一篇呢?没东西写了? 哈哈,当然不是!原因是当时的实现方案还是存在缺陷的,原因如下: 不够灵活,由于是以所有 ...
- Spring Boot 中使用自定义注解,AOP 切面打印出入参日志及Dubbo链路追踪透传traceId
一.使用背景 开发排查系统问题用得最多的手段就是查看系统日志,在分布式环境中一般使用 ELK 来统一收集日志,但是在并发大时使用日志定位问题还是比较麻烦,由于大量的其他用户/其他线程的日志也一起输出穿 ...
随机推荐
- QT之静态函数发送信号
一.简介 由于博主本人是初学者对QT的机制不了解,所以遇到了一个比较大的坑,特此记录一下.我遇到的问题是无法在静态函数中向另外一个类发送信号.解决办法:先将信号发送给同类中的普通函数,然后在从普通函数 ...
- Linux残留的EFI启动项删除后又恢复的问题
电脑Windows + Fedora双系统,UEFI启动,共用同一个EFI分区.现在删除了Fedora系统,那么应该将EFI分区中的Fedora启动项也删除之. 按照网上的办法,在Windows上,尝 ...
- 下载excel(接收文件流)
/** * 文件流转换 主要代码块,可自定义下载文件名称 * @param {} data */ export function download(data, titName) { if ( ...
- Expression 表达式动态生成
http://blog.csdn.net/duan1311/article/details/51769119 以上是拼装和调用GroupBy的方法,是不是很简单,只要传入分组列与合计列就OK了! 下面 ...
- 使用Eclipse的基本配置
因本人 IntelliJ IDEA 正版授权前些日子已到期,最近开始使用 Eclipse .体验开发了一阵子,觉得除了在界面美观与前端编辑的操作上 Eclipse 与 IDEA 差距还比较大以外,其他 ...
- pip更新升级和删除包
pip检测更新命令:pip list –outdated pip升级包命令:pip install --upgrade packagename pip卸载包命令:pip uninstall packa ...
- Vue3的新特性及相关的Composition API使用
首先 创建项目 Vue3 Vue3 相较于Vue2 的6大亮点: 1 性能快. 2 按需编译 体积更小 3 提供了组合API 类似于react 的React Hooks 4 更好的Ts支持 5 暴露了 ...
- 超详细的VMware安装Centos7教程
下载centos镜像 https://wiki.centos.org/Download 注:真正生产环境的oracle数据库一般是一整台服务器只用作数据库,不会安装其他应用,也不会安装xwindow图 ...
- jmeter跑脚本的注意事项
指标主要看以下几点: 1.jmeter性能测试的报告,不要看平均响应时间,而是看90%响应时间,一般不能超过3s,超过3s则不符合标准2.响应时间超过3s就要优化,但不是平均响应时间,因为最小响应时间 ...
- django把变量变成字段进行搜索
from ceshi.models import Student #引入model中的模型 获取前端请求的参数 searchKey=request.GET.get("key" ...