深入源码分析spring AOP

深入源码分析spring AOP

一、Spring AOP 核心概念

AOP(面向切面编程) 是 Spring 框架的核心功能之一,它通过动态代理技术,在不修改源代码的情况下,为业务逻辑横向添加通用功能(如日志、事务、权限等)。其核心思想是将业务代码非业务代码解耦,例如:

// 业务代码
public void transferMoney() { 
    // 转账逻辑...
}

// 非业务代码(日志记录)
public void log() { 
    System.out.println("记录操作日志");
}

通过 AOP,可以将 log() 方法自动织入到 transferMoney() 方法前后,无需手动调用 。

二、AOP 核心术语与源码实现

1. 核心概念
  • 切面(Aspect):包含切点和通知的模块,如日志切面、事务切面。源码中对应 Aspect 注解类。
  • 切点(Pointcut):定义拦截规则的表达式,如@Pointcut("execution(* com.example.service.*.*(..))")。源码通过Pointcut接口实现。
  • 通知(Advice):在切点处执行的动作,分为:
    • 前置通知(@Before):方法执行前触发。
    • 后置通知(@After):方法执行后触发。
    • 环绕通知(@Around):包裹目标方法,可控制执行流程(源码通过MethodInterceptor接口实现)。
  • 织入(Weaving):将切面逻辑插入到目标方法的过程。Spring 通过动态代理实现。
2. 动态代理机制

Spring AOP 底层通过 JDK 动态代理(基于接口)或 CGLIB 动态代理(基于继承)生成代理对象:

  • JDK 代理:通过 Proxy.newProxyInstance() 创建代理类,核心类是 JdkDynamicAopProxy
  • CGLIB 代理:通过生成目标类的子类实现,核心类是CglibAopProxy

源码关键流程

// 代理对象创建入口:AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (shouldProxy(bean)) {
        return createProxy(bean); // 创建代理对象
    }
    return bean;
}

三、AOP 应用实例

示例 1:日志切面
@Aspect
@Component
public class LogAspect {
    // 定义切点:拦截所有Service层方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void servicePointcut() {}

    // 前置通知
    @Before("servicePointcut()")
    public void beforeLog(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("方法执行前:" + methodName);
    }

    // 环绕通知
    @Around("servicePointcut()")
    public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知:开始执行");
        Object result = pjp.proceed(); // 执行目标方法
        System.out.println("环绕通知:执行结束");
        return result;
    }
}

执行流程

  1. Spring 容器初始化时扫描 @Aspect 注解。
  2. 通过 BeanPostProcessor 对目标 Bean 生成代理对象。
  3. 调用代理对象的方法时,按顺序执行拦截器链。

四、源码级原理解析

1. 代理对象生成
  • 入口AnnotationAwareAspectJAutoProxyCreator(Bean 后置处理器)在 Bean 初始化后触发代理生成。
  • 核心逻辑
    • 扫描所有 Advisor(封装了切点和通知)。
    • 使用DefaultAopProxyFactory根据目标对象选择代理方式(JDK 或 CGLIB)。
2. 拦截器链执行

当调用代理对象的方法时,会触发 ReflectiveMethodInvocation 类的 proceed() 方法:

public Object proceed() {
    if (currentInterceptorIndex == interceptors.size() - 1) {
        return invokeJoinpoint(); // 执行目标方法
    }
    // 按顺序执行拦截器(如前置、环绕、后置通知)
    MethodInterceptor interceptor = interceptors.get(currentInterceptorIndex++);
    return interceptor.invoke(this);
}

五、典型应用场景

  1. 声明式事务:通过@Transactional注解自动管理事务提交与回滚(源码通过TransactionInterceptor实现)。
  2. 权限校验:自定义注解 @RequireAuth,结合 AOP 在方法执行前验证用户权限。
  3. 接口限流:使用 Redis + AOP 统计接口调用频率。

六、总结

  • 核心价值:通过动态代理实现业务与非业务逻辑解耦,提升代码复用性和可维护性。
  • 源码关键点:代理对象的生成(AbstractAutoProxyCreator)和拦截器链的执行(ReflectiveMethodInvocation)。
  • 适用场景:日志、事务、权限等需要横向扩展功能的场景。

你可能感兴趣的:(Java基础知识,spring,java,后端)