拦截器链 --Spring AOP 实现横切逻辑的核心机制详解

构建 AOP 拦截器链是 Spring AOP 实现横切逻辑的核心流程,其本质是将多个切面(Aspect)的通知(Advice)按特定顺序组织成链式结构,在目标方法执行的前后动态拦截并执行这些逻辑。以下从核心组件构建流程执行顺序三个维度深度解析,并结合源码说明其工作机制。


一、AOP 拦截器链的核心组件

拦截器链的构建依赖以下核心组件,理解它们的职责是解析流程的基础:

1. Advisor(通知器)

Advisor 是 Spring AOP 的核心接口,定义了“何时(Pointcut)”和“如何(Advice)”执行横切逻辑。每个 Advisor 包含一个 Pointcut(切点)和一个 Advice(通知)。

  • Pointcut:匹配需要拦截的方法(如 execution(* com.example.service.*.*(..)))。
  • Advice:具体的横切逻辑(如 @Before@After@Around 等通知类型)。

2. Advice(通知)

Advice 是拦截器链中的“执行单元”,根据其在目标方法执行周期中的位置分为以下类型:

通知类型执行时机特点
@Before目标方法执行前无法阻止目标方法执行(除非抛出异常)。
@After目标方法执行后(无论成功或异常)无法获取目标方法返回值。
@AfterReturning目标方法成功返回后可获取目标方法返回值(通过 returning 属性绑定)。
@AfterThrowing目标方法抛出异常后可获取异常对象(通过 throwing 属性绑定)。
@Around包裹目标方法执行(可控制是否继续执行目标方法)可获取目标方法参数、返回值、异常,是功能最强大的通知类型。

3. ProxyFactory(代理工厂)

ProxyFactory 是 Spring AOP 中生成代理对象的核心类,负责:

  • 管理目标对象(Target)。
  • 收集所有匹配的 Advisor(拦截器)。
  • 生成代理对象(JDK 或 CGLIB)。

4. Advised(代理配置)

Advised 是 ProxyFactory 的内部接口,定义了代理的配置信息(如拦截器链、是否暴露代理等)。其实现类(如 AdvisedSupport)负责实际管理拦截器链。


二、拦截器链的构建流程

拦截器链的构建是一个动态组装过程,发生在 Spring 容器初始化或首次访问代理对象时。以下是关键步骤(结合源码):

1. 扫描切面并收集 Advisor

Spring 容器启动时,通过 BeanPostProcessor(如 AnnotationAwareAspectJAutoProxyCreator)扫描所有被 @Aspect 标记的切面类,提取其中的 @Pointcut@Before@After 等注解,生成对应的 Advisor 对象。

源码关键逻辑(简化自 AnnotationAwareAspectJAutoProxyCreator):

public class AnnotationAwareAspectJAutoProxyCreator extends AbstractAutoProxyCreator {

    @Override
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 扫描切面,收集所有 Advisor
        List<Advisor> advisors = findEligibleAdvisors(bean.getClass(), beanName);
        if (!advisors.isEmpty()) {
            // 生成代理对象
            return createProxy(bean.getClass(), beanName, advisors, new SingletonTargetSource(bean));
        }
        return bean;
    }

    private List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // 通过 AspectJ 表达式解析器,匹配所有符合条件的 Advisor
        List<Advisor> allAdvisors = new ArrayList<>();
        // 1. 收集所有 @Pointcut 定义的切点
        // 2. 收集所有 @Before/@After 等通知对应的 Advisor
        // 3. 过滤掉不匹配当前 bean 的 Advisor(通过 Pointcut 匹配)
        return allAdvisors;
    }
}

2. 排序 Advisor(可选)

若多个 Advisor 存在,可通过 @Order 注解或 Ordered 接口指定执行顺序(数值越小优先级越高)。未显式指定时,默认按切面类在类路径中的加载顺序排序。

3. 构建拦截器链

ProxyFactory 将收集到的 Advisor 转换为 Interceptor 链。每个 Advisor 对应一个 Interceptor(如 MethodBeforeAdviceInterceptorAroundAdviceInterceptor),链的顺序由 Advisor 的排序决定。

关键类

  • AdvisedSupport:管理拦截器链的核心类,内部通过 List<Advisor> 存储所有通知器。
  • InterceptorAndDynamicMethodMatcher:包装 Advisor 和动态匹配逻辑(如 @Pointcut 的动态匹配)。

4. 生成代理对象

根据目标对象是否实现接口,ProxyFactory 选择生成 JDK 动态代理或 CGLIB 代理。代理对象的 InvocationHandler(JDK)或 MethodInterceptor(CGLIB)会持有拦截器链,并在方法调用时触发拦截逻辑。


三、拦截器链的执行流程

当目标方法被调用时,代理对象会触发拦截器链的执行。以下是典型的执行顺序(以 @Around 通知为例):

1. 调用代理对象的方法

客户端通过代理对象调用目标方法(如 userService.createUser())。

2. 触发拦截器链

代理的 InvocationHandler(JDK)或 MethodInterceptor(CGLIB)捕获方法调用,开始执行拦截器链。

3. 按顺序执行拦截器

拦截器链按排序后的顺序依次执行,每个拦截器根据其类型决定是否继续执行后续逻辑:

(1)@Around 通知
  • 执行前:记录方法开始时间、参数等信息。
  • 控制是否继续:通过调用 proceed() 方法决定是否执行后续拦截器或目标方法。若不调用 proceed(),目标方法不会执行。
(2)@Before 通知
  • 直接执行前置逻辑(如日志记录),然后自动调用后续拦截器或目标方法(无需显式调用 proceed())。
(3)目标方法执行

若所有前置拦截器(@Before@Around 中调用 proceed())执行完毕,目标方法被调用。

(4)@AfterReturning 通知
  • 目标方法成功返回后执行(可获取返回值)。
(5)@AfterThrowing 通知
  • 目标方法抛出异常后执行(可获取异常对象)。
(6)@After 通知
  • 目标方法执行完成后(无论成功或异常)执行。

4. 返回结果

最终结果(目标方法返回值或异常)通过拦截器链传递回客户端。


四、Mermaid 流程图:拦截器链的构建与执行

1. 拦截器链构建流程图

graph TD
    A[Spring 容器初始化] --> B[扫描 @Aspect 切面]
    B --> C[提取 @Pointcut、@Before、@After 等注解]
    C --> D[生成 Advisor(切点+通知)]
    D --> E[按 @Order 排序 Advisor]
    E --> F[ProxyFactory 生成代理对象]
    F --> G[代理对象持有拦截器链]

在这里插入图片描述

2. 拦截器链执行流程图

graph TD
    A["客户端调用代理方法"] --> B["触发 InvocationHandler"]
    B --> C["执行拦截器链"]
    C --> D{"@Around 通知: 调用 proceed()?"}
    D -- 是 --> E["@Before 通知"]
    D -- 否 --> Z[结束链,不执行目标方法]
    E --> F["@AfterReturning 通知(目标方法成功"]
    F --> G["@After 通知"]
    E --> H["目标方法执行"]
    H --> I{"@AfterThrowing 通知(目标方法异常)"}
    I --> G
    G --> Z

在这里插入图片描述


五、关键源码与调试技巧

1. 查看拦截器链

通过调试 AdvisedSupport 类的 advisors 字段,可查看当前代理对象的所有拦截器:

// 在 ProxyFactory 中获取 AdvisedSupport
AdvisedSupport advised = (AdvisedSupport) ((Advised) proxy).getAdvisors();
for (Advisor advisor : advised.getAdvisors()) {
    System.out.println("Advisor: " + advisor);
}

2. 动态修改拦截器链

Spring 允许通过 AopConfig 动态添加/移除 Advisor(需手动触发代理更新):

// 获取代理对象的 Advised 支持
Advised advised = (Advised) targetObject;
// 添加新的 Advisor
advised.addAdvisor(new MyAdvisor());
// 重新生成代理(可选)

六、总结

拦截器链是 Spring AOP 实现横切逻辑的核心机制,其构建流程涉及切面扫描、Advisor 生成、排序、代理生成,执行流程则通过动态代理触发拦截器的链式调用。理解这一过程有助于:

  • 调试 AOP 逻辑(如查看拦截器顺序)。
  • 自定义拦截器(如实现 MethodInterceptor)。
  • 优化性能(如减少不必要的拦截器)。

通过结合源码和 Mermaid 流程图, 我们可更直观地掌握 AOP 拦截器链的工作原理,从而在实际项目中灵活应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值