Skip to content
章节导航

切面,可以大大减少工程中的冗余代码

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 AOPAspectJ
织入时机运行时(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;
    }

}