惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 郭慕荣

Docker部署zookeeper总结 Mac中git ssh的配置(GitLab) Java 类加载机制 面试题(一) 如何监控和调优JVM性能? jvm常用的参数有哪些? 怎么配置? hashmap 和currenthashmap 的原理?详解一下 Java dubbo spring springboot中的spi机制 spring中常见的两种代理模式 Redis的zset 面试汇总 drools 规则引擎在线化配置 - 郭慕荣 springcloud中常用的注解详解 springcloud中网关gateway总结 spring是怎么解决循环依赖的? MySQL 死锁 怎么处理? 在写left join的时候 是大表在左侧 还是小表在左侧(二) 在写left join的时候 是大表在左侧 还是小表在左侧(一) nacos客户端(接口调用者)如何感知被调用服务下线? (二) nacos客户端(接口调用者)如何感知被调用服务下线?(一) 在MySQL中 redolog undolog binlog 写入的场景,顺序 - 郭慕荣
aop在项目中使用的场景?怎么使用?
郭慕荣 · 2025-10-28 · via 博客园 - 郭慕荣

AOP(面向切面编程)是一种通过 “横切” 代码结构,将分散在多个模块中的公共逻辑(如日志、事务、权限等)集中管理的编程思想。其核心价值是解耦业务逻辑与横切逻辑,减少重复代码,提高可维护性。在实际项目中,AOP 的应用场景非常广泛,以下从具体场景、实现方式(以 Spring AOP 为例)展开说明。

在讲场景前,先明确 AOP 的几个关键术语(以 Spring AOP 为例):

  • 切面(Aspect):封装横切逻辑的类(如 “日志切面”“事务切面”),通常用@Aspect注解标记。
  • 切点(Pointcut):定义 “哪些方法需要被拦截”,通过表达式(如execution(* com.xxx.service.*.*(..)))指定拦截范围。
  • 通知(Advice):切面中具体的横切逻辑,包括:
    • 前置通知(@Before):方法执行前执行;
    • 后置通知(@After):方法执行后(无论是否异常)执行;
    • 返回通知(@AfterReturning):方法正常返回后执行;
    • 异常通知(@AfterThrowing):方法抛出异常后执行;
    • 环绕通知(@Around):包裹方法执行,可控制方法是否执行、修改入参 / 返回值。
  • 连接点(Joinpoint):程序执行过程中可被拦截的点(如方法调用、字段访问等,Spring AOP 仅支持方法级连接点)。

需求:记录接口 / 方法的调用日志(入参、出参、执行时间、调用者 IP 等),用于问题排查、审计追踪。痛点:如果在每个接口手动写日志代码,会导致大量重复,且修改日志格式需改动所有地方。AOP 解决方案:通过切面统一拦截目标方法,自动记录日志。

需求:数据库操作中,确保一系列操作(如 “扣库存 + 下单”)要么全成功,要么全失败(ACID 特性)。痛点:手动编写try-catch+commit/rollback代码繁琐,且容易遗漏事务回滚。AOP 解决方案:Spring 的@Transactional注解底层基于 AOP,通过环绕通知自动管理事务生命周期(开启→提交 / 回滚)。

需求:接口调用前验证用户是否有权限(如 “管理员才能删除数据”),无权限则拒绝访问。痛点:在每个接口手动写权限校验逻辑,代码冗余,且权限规则变更需修改所有接口。AOP 解决方案:通过前置通知拦截接口方法,统一校验权限,无权限则抛出异常。

需求:接口抛出异常时,统一转换为友好的响应格式(如{code:500, msg:"服务器异常"}),避免直接返回堆栈信息。痛点:每个方法手动try-catch处理异常,代码冗余,且格式难以统一。AOP 解决方案:通过异常通知拦截方法抛出的异常,统一封装响应结果。

需求:统计核心方法的执行时间,识别性能瓶颈(如 “查询接口是否超过 100ms”)。痛点:手动在方法前后记录时间戳,代码侵入性强,且难以批量统计。AOP 解决方案:通过环绕通知记录方法执行前后的时间,计算耗时并输出(或上报监控系统)。

需求:对高频查询接口(如 “商品详情查询”)添加缓存,减少数据库压力。痛点:手动写 “查缓存→无则查库→更新缓存” 逻辑,代码重复,且缓存策略难以统一管理。AOP 解决方案:通过环绕通知拦截查询方法,自动执行缓存逻辑(如结合@Cacheable注解)。

以 “接口日志记录” 和 “权限校验” 为例,展示 AOP 的实现步骤。

Spring 项目中需引入 AOP 依赖(Maven):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

目标:拦截所有 Controller 层接口,记录请求参数、响应结果、执行时间、IP 地址。

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

目标:拦截标注了@RequirePermission注解的方法,验证用户是否拥有指定权限。

  1. 定义权限注解:
import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequirePermission {
    String value(); 
  1. 实现权限切面: 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class PermissionAspect {

    
  1. 在接口中使用:
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    
  1. 切点表达式精准性:避免切点范围过大(如拦截所有方法),导致性能损耗;也避免过小,遗漏需要拦截的方法。常用表达式:
    • execution(* com.xxx.service.*.*(..)):拦截 service 包下所有类的所有方法;
    • @annotation(com.xxx.annotation.Log):拦截标注了 @Log 注解的方法。
  2. 通知执行顺序:多个切面拦截同一方法时,可通过@Order(n)指定优先级(n 越小优先级越高)。
  3. 性能影响:环绕通知会包裹方法执行,过度使用可能增加耗时,核心高频接口需谨慎。
  4. 异常处理:通知中若抛出未捕获的异常,会影响目标方法执行(如事务切面需确保异常正确传播)。

AOP 的核心是 “将横切逻辑集中管理”,在日志、事务、权限等场景中能极大减少重复代码,提高项目可维护性。Spring AOP 通过注解(@Aspect@Pointcut@Around等)简化了 AOP 的使用,只需定义切面、切点和通知,即可实现对目标方法的无侵入式增强。实际项目中,需根据业务场景选择合适的通知类型,并注意切点精准性和性能影响。