简介

我们在文章《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. CF620E New Year Tree(树形+dfs序+线段树+状态压缩)

    题目链接 题目大意 \(~~\)给出一棵 nn 个节点的树,根节点为 11.每个节点上有一种颜色 c\(_{i}\) 和m 次操作.操作有两种: \(~~~~\) 1. 1\(~\)u\(~\)c:将 ...

  2. 「浙江理工大学ACM入队200题系列」问题 B: 零基础学C/C++12——求平均值

    本题是浙江理工大学ACM入队200题第二套中的B题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

  3. MYSQL数据库的导出和导入

    一.连接服务器查看数据库 使用连接工具(xshell6等)连接到数据库所在服务器,执行命令查询需要导出的数据库 1.输入数据库管理员账号密码进入控制台:mysql -uroot -p123456    ...

  4. Websocket集群解决方案

    最近在项目中在做一个消息推送的功能,比如客户下单之后通知给给对应的客户发送系统通知,这种消息推送需要使用到全双工的websocket推送消息. 所谓的全双工表示客户端和服务端都能向对方发送消息.不使用 ...

  5. 从0到1搭建redis6.0.7续更~

    "心有所向,日复一日,必有精进" 前言: 想必大家看完我之前写的搭建redis服务器,大家都已经把redis搭建起来了吧如果没有搭建起来的小可爱请移步这里哦从0到1搭建redis6 ...

  6. WPF之BackgroundWorker

    BackgroundWorker类允许您在单独的线程上执行某个可能导致用户界面(UI)停止响应的耗时操作,下面来介绍一下这个线程类BackgroundWorker,大家可以结合这位大佬的这篇文章,说的 ...

  7. 查看、校验、归档…带你掌握openGauss账本数据库

    ​摘要:账本数据库融合了区块链思想,将用户操作记录至两种历史表中:用户历史表和全局区块表. 本文分享自华为云社区<openGauss账本数据库,你不知道的那些事儿>,作者:Gauss松鼠会 ...

  8. hwlog----types.go

    // Copyright(C) 2021. Huawei Technologies Co.,Ltd. All rights reserved.// Package hwlog provides the ...

  9. Go语言核心36讲52

    你好,我是郝林. 专栏到这里,就要结束了. 差不多在半年以前(2018年的第二个季度),极客时间的总编辑郭蕾找到我,说想让我写一个关于Go语言的技术专栏. 我那时候还在轻松筹担任大数据负责人,管理着四 ...

  10. laravel框架 forelse和foreach

    1. @forelse($data as $v) 循环数据内容..... @empty 数据为空提示... @endforelse 2. @foreach($data as $v) 循环数据内容... ...