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

推荐订阅源

WordPress大学
WordPress大学
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园 - 聂微东
博客园 - 【当耐特】
Last Week in AI
Last Week in AI
量子位
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog
B
Blog RSS Feed
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
GbyAI
GbyAI
Jina AI
Jina AI
宝玉的分享
宝玉的分享
腾讯CDC
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
D
Docker
博客园_首页
N
News and Events Feed by Topic
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Help Net Security
Help Net Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
Cisco Blogs
F
Fortinet All Blogs
SecWiki News
SecWiki News
AI
AI
S
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The Last Watchdog
The Last Watchdog
Martin Fowler
Martin Fowler
A
About on SuperTechFans
T
Troy Hunt's Blog
P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
Hacker News: Ask HN
Hacker News: Ask HN
F
Full Disclosure
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
I
InfoQ
S
Security @ Cisco Blogs
Project Zero
Project Zero
Simon Willison's Weblog
Simon Willison's Weblog
C
Cyber Attacks, Cyber Crime and Cyber Security
J
Java Code Geeks
N
News | PayPal Newsroom
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
H
Hacker News: Front Page

博客园 - 郭慕荣

彻底搞懂 Codex Skill 与插件:区别、试用、核心作用、项目落地全指南(程序员实战向) Codex Skill 和插件到底有什么区别?程序员如何在项目中落地使用 claudecode 配置防止配置文件泄露总结 Claude code分析外部文件总结 Claude code三种模式详解 hasCompletedOnboarding详解 Claudecode 有哪些常用的命令 claude.md文件详解 claude code 的setting文件详解 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 的使用,只需定义切面、切点和通知,即可实现对目标方法的无侵入式增强。实际项目中,需根据业务场景选择合适的通知类型,并注意切点精准性和性能影响。