Skip to content

Spring AOP 面向切面编程

TIP

AOP(Aspect Oriented Programming)通过预编译方式和运行期动态代理实现程序功能的统一维护,将日志、事务等横切关注点与业务逻辑分离。

AOP 核心概念

概念说明
Aspect(切面)横切关注点的模块化,如日志切面
Join Point(连接点)程序执行中的某个点,如方法调用
Pointcut(切点)匹配连接点的表达式
Advice(通知)在切点上执行的动作
Weaving(织入)将切面应用到目标对象的过程

通知类型

java
@Aspect
@Component
public class LogAspect {

    // 前置通知
    @Before("execution(* com.example.service.*.*(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("前置通知: " + joinPoint.getSignature().getName());
    }

    // 后置通知(无论是否异常都执行)
    @After("execution(* com.example.service.*.*(..))")
    public void after() {
        System.out.println("后置通知");
    }

    // 返回通知(方法正常返回后执行)
    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void afterReturning(Object result) {
        System.out.println("返回通知, 结果: " + result);
    }

    // 异常通知
    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "e")
    public void afterThrowing(Exception e) {
        System.out.println("异常通知: " + e.getMessage());
    }

    // 环绕通知(功能最强大)
    @Around("execution(* com.example.service.*.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = pjp.proceed();
        long duration = System.currentTimeMillis() - start;
        System.out.println(pjp.getSignature().getName() + " 耗时: " + duration + "ms");
        return result;
    }
}

切点表达式

java
// 匹配指定包下的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}

// 匹配带有 @Log 注解的方法
@Pointcut("@annotation(com.example.annotation.Log)")
public void logAnnotation() {}

// 组合切点
@Around("serviceLayer() && logAnnotation()")
public Object combinedAdvice(ProceedingJoinPoint pjp) throws Throwable {
    // ...
}

实现原理

Spring AOP 基于动态代理实现:

  • JDK 动态代理:目标类实现了接口时使用
  • CGLIB 代理:目标类未实现接口时使用
java
// JDK 动态代理示例(简化)
public class JdkProxy implements InvocationHandler {
    private Object target;

    public Object createProxy(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置处理");
        Object result = method.invoke(target, args);
        System.out.println("后置处理");
        return result;
    }
}

TIP

实际开发中常用 AOP 实现日志记录、权限校验、事务管理、性能监控等功能。