切面,可以大大减少工程中的冗余代码
AOP 执行时机,在 Service 前后执行,将分散在各个业务逻辑代码中的相同代码通过横向切割的方式抽取到独立模块中 
AOP 核心术语
- 切面(Aspect):申明这是一个切面类,交由 Spring Bean 去管理,切面也是一个 Spring Bean
- 连接点(Join Point):表明在程序中明确定义一个点,包括方法调用,类成员访问以及程序块执行等等
- 切点(Pointcut):连接点的一个结合
- 织入(Weaving):把切面接连到其他的一个程序类型或者对象上
- 通知(Advice):包含 Before、after returning、after throwing、after finally、around(最常用)
- 目标对象(Target)
Spring AOP vs AspectJ
| 特性 | Spring AOP | AspectJ |
|---|---|---|
| 织入时机 | 运行时(Runtime) | 编译时、类加载时、运行时 |
| 连接点支持 | 仅方法执行 | 方法、构造器、字段等全面支持 |
| 性能 | 较慢(动态代理) | 快(字节码织入) |
| 复杂性 | 简单,Spring 集成好 | 复杂,功能强大 |
| 代理机制 | JDK 动态代理或 CGLIB | 字节码操作 |
| 目标对象限制 | 必须 Spring 管理的 Bean | 任意对象 |
| 自我调用 | 不支持(代理问题) | 支持 |
| 配置方式 | 注解或XML | 注解、代码或XML |
AOP 切面案例
需要的依赖
xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>编写注解
java
/**
* 用于方法返回打印日志的注解
*
* @author 朔风
* @date 2026-01-14 15:51
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ReturnLog {
String prefix() default StringUtils.EMPTY;
}切面实现
java
/**
* 方法返回打印日志切面
*
* @author 朔风
* @date 2026-01-14 15:53
*/
@Aspect
@Component
public class ReturnLogAspect {
private static final Logger logger = LoggerFactory.getLogger(ReturnLogAspect.class);
@Pointcut("@annotation(com.github.itdachen.aop.ReturnLog)")
private void pointcut() {}
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取目标类名称、方法名称
String clazzName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
// 调用目标方法
Object result = joinPoint.proceed();
// 获取切点信息
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
ReturnLog returnLog = method.getAnnotation(ReturnLog.class);
// 记录日志
logger.info("ReturnLogAspect {} ...", returnLog.prefix());
return result;
}
}
剑鸣秋朔