
自定义注解 + AOP 记录接口访问日志
@Pointcut()的execution、@annotation等参数说明 Java 自定义注解及使用场景
发布日期:2021-05-08 13:47:10
浏览次数:25
分类:精选文章
本文共 3775 字,大约阅读时间需要 12 分钟。
AOP(面向切面编程)简明介绍
一、AOP的基本概念
1. AOP是什么
AOP(Aspect Oriented Programming,面向切面编程)是一种通过预编译和运行时动态代理,在不修改源代码的情况下为程序添加功能的技术。
实现方式主要有两种:JDK动态代理和CGLIB代理。前者基于接口,后者基于子类。两种代理方式各有优劣,选择时需根据实际需求权衡。
2. AOP可以实现的功能
- 统计接口访问次数
- 增强功能:在不改动代码的情况下,为接口增加额外功能
3. 切面执行顺序
正常执行顺序:方法执行→切面1→切面2→方法返回
异常执行顺序:方法执行→切面1→异常处理→切面2→方法抛出异常
4. AOP注解
- @Aspect:定义切面,通常用于标注切入点和通知逻辑
- @Pointcut:定义切入点,用于指定切面执行的连接点
- Advice:通知,用于在切入点处执行增强逻辑
- JointPoint:连接点,表示程序运行中的某个阶段点(如方法调用、异常抛出等)
- Advisor:增强,包含Pointcut和Advice的综合体,描述增强的位置和方式
5. 自定义注解
在AOP中,自定义注解可以帮助更灵活地管理切面。常用的注解包括:
- @Target:描述注解作用的目标范围,常用值有:METHOD、PACKAGE、PARAMETER、TYPE
- @Retention:指定注解保留的时间范围,常用值有:SOURCE、CLASS、RUNTIME
- @Documented:标记注解为文档化,确保注解信息能被生成 javadoc
二、AOP实战代码
1. 依赖引入
org.aspectj aspectjrt 1.9.4 org.aspectj aspectjweaver 1.9.4 cglib cglib 3.2.12
2. AOP示例
通过以下示例可以更直观地理解AOP的实际应用:
import com.example.demo.module.annotation.SystemLog;import com.example.demo.module.utils.AtomicCounter;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.*import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;@Component@Aspectpublic class ApiLogAopAction { private static final Logger LOGGER = LoggerFactory.getLogger(ApiLogAopAction.class); ThreadLocalstartTime = new ThreadLocal<>(); @Autowired HttpServletRequest request; @Pointcut("@annotation(com.example.demo.module.annotation.SystemLog)") public void log() {} @Before("log()") public void doBefore(JoinPoint joinPoint) { startTime.set(System.currentTimeMillis()); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); SystemLog annotation = signature.getMethod().getAnnotation(SystemLog.class); AtomicCounter.init(annotation.module(), request.getRequestURI()); AtomicCounter.getInstance().increaseVisit(request.getRequestURI()); } @AfterReturning(returning = "returnVal", pointcut = "log()") public void doAfterReturning(JoinPoint joinPoint, Object returnVal) { LOGGER.info("URI:[{}], 耗费时间:[{}] ms, 访问次数:{}", request.getServletPath(), System.currentTimeMillis() - startTime.get(), AtomicCounter.getInstance().increaseSuccess(request.getRequestURI())); } @AfterThrowing(pointcut = "log()") public void doAfterThrowing(JoinPoint joinPoint) { LOGGER.info("接口访问失败,URI:[{}], 耗费时间:[{}] ms", request.getServletPath(), AtomicCounter.getInstance().increaseFail(request.getRequestURI())); } @After("log()") public void doAfter(JoinPoint joinPoint) { LOGGER.info("End.{}", AtomicCounter.getInstance().getValue(request.getRequestURI())); }}
3. 自定义注解示例
import java.lang.annotation.*;/** * @Title SystemLog * @Description 接口日志注解 * @author ACGkaka * @date 2021/4/1 11:36 */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface SystemLog { String module() default ""; String method() default ""; String operateType() default "OTHER"; String logType() default "0";}
4. 定义接口,进行测试
import com.example.demo.module.annotation.SystemLog;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class DemoController { @GetMapping("/index") @SystemLog(module = "首页", method = "hello", operateType = "SELECT", logType = "1") public String index() { return "Hello World.
"; } @GetMapping("login") @SystemLog(module = "首页", method = "login", operateType = "LOGIN", logType = "1") public String login() { int i = 1 / (Math.random() > 0.5 ? 0 : 1); return "测试报错的AOP方法"; }}
参考文章
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月19日 02时09分37秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
CentOS 6.4 yum安装chrome
2023-01-26
CentOS 6.4下编译安装MySQL 5.6.14
2023-01-26
Centos 6.4搭建网络源
2023-01-26
CentOS 6.5 Zabbix-server安装
2023-01-26
CentOS 6.5 伪分布式 安装 hadoop 2.6.0
2023-01-26
CentOS 6.5 配置IP地址的三种方法
2023-01-26
CentOS 6.9 yum 和源码安装htop,适用于centOS 7
2023-01-26
centos 64位 hadoop编译
2023-01-26
CentOS 7 / RHEL 7 上安装 LAMP + phpMyAdmin
2023-01-26
CentOS 7更换yum源
2023-01-26
CentOS 7 安装 postgreSQL 9.4
2023-01-26
centos 7安装docker
2023-01-26
CentOS 7 巨大变动之 systemd 取代 SysV的Init
2023-01-26
Centos 7 快速安装FTP服务
2023-01-26
centos 7 静态IP,指定DNS
2023-01-26
centos 7.3 启动mysql_centos7.3 搭建MySQL
2023-01-26
Centos 7.5 docker 容器怎么设置开机自启
2023-01-26
Centos 7.5 SSH改别的端口连接不上,只有默认端口才行(未解决)
2023-01-26
Centos 7.5 如何安装VMware Tools工具
2023-01-26
Centos 7.5 新磁盘创建和挂载XFS文件系统
2023-01-26