简介

我们在文章《Spring AOP与AspectJ的对比及应用》介绍了AOP的使用,这篇文章讲解一下AOP与注解的整合,通过注解来使用AOP,会非常方便。为了简便,我们还是来实现一个计时的功能。

整合过程

首先创建一个注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PkslowLogTime {
}

然后在一个Service中使用注解:

@Service
@Slf4j
public class TestService {
@PkslowLogTime
public void fetchData() {
log.info("fetchData");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

这个Service的方法会在Controller中调用:

@GetMapping("/hello")
public String hello() {
log.info("------hello() start---");
test();
staticTest();
testService.fetchData();
log.info("------hello() end---");
return "Hello, pkslow.";
}

接着是关键一步,我们要实现切面,来找到注解并实现对应功能:

@Aspect
@Component
@Slf4j
public class PkslowLogTimeAspect {
@Around("@annotation(com.pkslow.springboot.aop.PkslowLogTime) && execution(* *(..))")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("------PkslowLogTime doAround start------");
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); // Get intercepted method details
String className = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName(); // Measure method execution time
StopWatch stopWatch = new StopWatch(className + "->" + methodName);
stopWatch.start(methodName);
Object result = joinPoint.proceed();
stopWatch.stop();
// Log method execution time
log.info(stopWatch.prettyPrint());
log.info("------PkslowLogTime doAround end------");
return result;
}
}

@Around("@annotation(com.pkslow.springboot.aop.PkslowLogTime) && execution(* *(..))")这个表达式很关键,如果不对,将无法正确识别;还有可能出现多次调用的情况。多次调用的情况可以参考:Stackoverflow

这里使用了Spring的StopWatch来计时。

测试

通过maven build包:

$ mvn clean package

日志可以看到有对应的织入信息:

[INFO] Join point 'method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:22) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
[INFO] Join point 'method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:22) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
[INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.test())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:31) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
[INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.test())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:31) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
[INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.staticTest())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:37) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
[INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.staticTest())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:37) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
[INFO] Join point 'method-execution(void com.pkslow.springboot.service.TestService.fetchData())' in Type 'com.pkslow.springboot.service.TestService' (TestService.java:12) advised by around advice from 'com.pkslow.springboot.aop.PkslowLogTimeAspect' (PkslowLogTimeAspect.class(from PkslowLogTimeAspect.java))

启动应用后访问接口,日志如下:

总结

通过注解可以实现很多功能,也非常方便。而且注解还可以添加参数,组合使用更完美了。

代码请看GitHub: https://github.com/LarryDpk/pkslow-samples

Springboot整合AOP和注解,实现丰富的切面功能的更多相关文章

  1. SpringBoot整合定时任务----Scheduled注解实现(一个注解全解决)

    一.使用场景 定时任务在开发中还是比较常见的,比如:定时发送邮件,定时发送信息,定时更新资源,定时更新数据等等... 二.准备工作 在Spring Boot程序中不需要引入其他Maven依赖 (因为s ...

  2. spring框架aop用注解形式注入Aspect切面无效的问题解决

    由于到最后我的项目还是有个邪门的错没解决,所以先把文章大概内容告知: 1.spring框架aop注解扫描默认是关闭的,得手动开启. 2.关于Con't call commit when autocom ...

  3. 【使用篇二】SpringBoot整合aop(13)

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...

  4. springboot整合aop实现网站访问日志记录

    目的: 统一日志输出格式,统计访问网站的ip. 思路: 1.针对不同的调用场景定义不同的注解,目前想的是接口层和服务层. 2.我设想的接口层和服务层的区别在于: (1)接口层可以打印客户端IP,而服务 ...

  5. SpringBoot整合Mybatis使用注解或XML的方式开发

    2018-6-4 补充mybatis-spring-boot注解的使用 1.导包 只需要再导入mysql+mybatis两个包 <dependency> <groupId>or ...

  6. SpringBoot整合AOP

    一.创建LogComponent类     类上加上@Component和@Aspect 表示把该类注册成spring组件和aop         二.创建6个方法     2.1     @Poin ...

  7. springboot整合mybatis之注解方式

    1. 创建maven项目,工程目录如下图 2. 在pom.xml文件中添加mybatis依赖. 3. 创建实体类,并生成construct方法,getter和setter方法.同时在数据库中创建对应的 ...

  8. SpringBoot整合quartz实现动态启动,停止定时任务功能

    注意:这个方法当程序重启之后会失效,所以必须将定时任务持久化到数据库,然后程序启动的时候重新把数据库的定时任务加载到quartz中 springboot程序启动初始化代码参考:https://www. ...

  9. Spring AOP通过注解的方式设置切面和切入点

    切面相当于一个功能的某一个类,切入点是这个类的某部分和需要额外执行的其他代码块,这两者是多对多的关系,在代码块处指定执行的条件. Aspect1.java package com.yh.aop.sch ...

  10. Springboot的日志管理&Springboot整合Junit测试&Springboot中AOP的使用

    ==============Springboot的日志管理============= springboot无需引入日志的包,springboot默认已经依赖了slf4j.logback.log4j等日 ...

随机推荐

  1. Java 多线程写zip文件遇到的错误 write beyond end of stream!

    最近在写一个大量小文件直接压缩到一个zip的需求,由于zip中的entry每一个都是独立的,不需要追加写入,也就是一个entry文件,写一个内容, 因此直接使用了多线程来处理,结果就翻车了,代码给出了 ...

  2. Codeforces Round #811 (Div. 3)D. Color with Occurrences

    题目大意:给出一个文章t和n个字符串s1,s2...sn: 问能否用这n个字符串将整个文章覆盖: 思路:贪心(最小区间覆盖) 记录每个字符串能够覆盖的所有位置(起点,终点,编号) 排序后贪心的求出是否 ...

  3. SpringBoot怎么自定义一个Starter ?

    小伙伴们曾经可能都经历过整天写着CURD的业务,都没写过一些组件相关的东西,这篇文章记录一下SpringBoot如何自定义一个Starter. 原理和理论就不用多说了,可以在网上找到很多关于该方面的资 ...

  4. tcp网络交互的理解 以及代码实现

    服务端 import socketserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server.bind(("127.0. ...

  5. (工具) 性能测试基准软件 lmBench (待补充)

    1. lmBench 介绍 Lmbench是一套简易,可移植的,符合ANSI/C标准为UNIX/POSIX而制定的微型测评工具.一般来说,它衡量两个关键特征:反应时间和带宽.Lmbench旨在使系统开 ...

  6. Android Studio打开时报错if you already hava 64-bit JDK installed,define a JAVA_HOME

    出现这个问题不知道改了什么导致的,卸载了重新安装也是不行. 以及到高级设置中进行配置jdk也是无效, 解决方法为需要在路径 C:\Users\你自己的用户名\AppData\Roaming\Googl ...

  7. vscode分级文件夹

    如果vscode不小心设置成文件独立展开,一堆文件看着很乱 这样设置 首选项-设置-功能-资源管理器-compack folders 就可以折叠文件夹了

  8. sublime text设置build system automatic提示no build system

    解决办法: 将: "selector": "source.asm" 改为: "selector": ["source.asm&qu ...

  9. redis集群之分片集群的原理和常用代理环境部署

    上篇文章刚刚介绍完redis的主从复制集群,但主从复制集群主要是为了解决redis集群的单点故障问题,通过整合哨兵能实现集群的高可用:但是却无法解决数据容量以及单节点的压力问题,所以本文继续介绍red ...

  10. 【Impala】概念、原理、内外部shell、建库建表、分区、查询、自定义函数、存储压缩

    一.基本概念 1.介绍 对HDFS.Hbase数据的高性能.低延迟的交互式SQL查询功能 2.优缺点 优点:基于内存运算,无需写入磁盘,无需转化为MR,支持Data Locality调度(数据和计算在 ...