Spring AOP实现原理

Spring AOP(Aspect-Oriented Programming)是 Spring 框架的核心功能之一,它通过 动态代理字节码增强 技术,在不修改目标类代码的前提下,实现日志记录、权限控制、事务管理等功能。其底层实现涉及多个核心类和复杂的代理生成逻辑。


🧠 一、Spring AOP 的核心概念

✅ 1. AOP 的基本术语

术语含义
Aspect(切面)横切关注点的模块化,如日志、事务等
JoinPoint(连接点)程序执行过程中的某个点,如方法调用、异常抛出等
Pointcut(切入点)定义哪些连接点需要被拦截
Advice(通知)切面在特定连接点上执行的操作
Weaving(织入)将切面应用到目标对象并生成代理对象的过程

🔄 二、Spring AOP 的实现原理概述

Spring AOP 的核心是 动态代理AOP 代理工厂。其基本流程如下:

1. 解析切面(Aspect) → 2. 创建代理工厂(ProxyFactory) → 3. 生成代理对象(JDK / CGLIB) → 4. 方法调用时拦截并执行切面逻辑

📦 三、关键类与组件

类名作用
@EnableAspectJAutoProxy启用 AOP 自动代理
AnnotationAwareAspectJAutoProxyCreatorAOP 自动代理创建器
ProxyFactory创建代理对象的核心类
JdkDynamicAopProxy使用 JDK 动态代理
CglibAopProxy使用 CGLIB 代理(子类继承)
Advisor / Advice / Pointcut描述切面逻辑和匹配规则

🧱 四、Spring AOP 的实现流程详解

✅ 1:启用 AOP 支持(@EnableAspectJAutoProxy

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
}
  • @EnableAspectJAutoProxy 注解会导入 AspectJAutoProxyRegistrar
  • AspectJAutoProxyRegistrar 会注册 AnnotationAwareAspectJAutoProxyCreator Bean。
public class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    }
}

✅ 2:自动代理创建器(AnnotationAwareAspectJAutoProxyCreator

该类继承自 AbstractAutoProxyCreator,负责在 Bean 创建过程中生成代理对象。

核心方法:postProcessAfterInitialization()
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        // 获取所有匹配的 Advisor
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            // 创建代理对象
            return createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        }
    }
    return bean;
}

✅ 3:创建代理对象(ProxyFactory

ProxyFactory 是创建代理的核心类,根据目标类是否实现接口选择代理方式:

protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this.config);
    proxyFactory.setTargetSource(targetSource);

    // 添加拦截器(切面逻辑)
    proxyFactory.addAdvisors(specificInterceptors);

    // 决定使用 JDK 动态代理还是 CGLIB
    proxyFactory.setProxyTargetClass(proxyTargetClass);
    
    return proxyFactory.getProxy(getProxyClassLoader());
}

✅ 4:生成代理对象(JdkDynamicAopProxyCglibAopProxy

4.1 JDK 动态代理(JdkDynamicAopProxy

适用于目标类实现了接口的情况:

public Object getProxy(@Nullable ClassLoader classLoader) {
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
4.2 CGLIB 代理(CglibAopProxy

适用于目标类没有实现接口的情况:

public Object getProxy(@Nullable ClassLoader classLoader) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(proxySuperClass);
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setCallback(new DynamicAdvisedInterceptor(this.advised));
    return enhancer.create();
}

✅ 5:拦截方法调用(MethodInterceptor

当代理对象的方法被调用时,会进入 DynamicAdvisedInterceptor(CGLIB)或 JdkDynamicAopProxy(JDK)的 invoke() 方法。

示例:DynamicAdvisedInterceptor.invoke()
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    MethodInvocation invocation = new CglibMethodInvocation(proxy, target, method, args, targetClass, methodProxy, this.advised);
    return invocation.proceed(); // 执行拦截器链
}

✅ 6:执行拦截器链(MethodInterceptor

拦截器链由多个 MethodInterceptor 组成,按顺序执行:

public Object proceed() throws Throwable {
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint(); // 执行目标方法
    }

    Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); // 递归执行
}

⚙️ 五、切面逻辑的执行顺序(Advice 顺序)

Spring AOP 支持多种类型的 Advice,它们的执行顺序如下:

类型注解执行顺序
Before Advice@Before在目标方法执行前执行
After Returning Advice@AfterReturning在目标方法成功返回后执行
After Throwing Advice@AfterThrowing在目标方法抛出异常后执行
After (Finally) Advice@After在目标方法执行后(无论是否异常)执行
Around Advice@Around包裹目标方法,可控制是否执行目标方法

❗ 六、AOP 常见问题与解决方案

Q1: AOP 为什么不能拦截 private 方法?

因为 Spring AOP 基于动态代理,JDK 动态代理只能拦截 public 方法。即使是 CGLIB 代理,也默认不处理非 public 方法。

Q2: AOP 为什么不能拦截内部调用(self-invocation)?

因为代理对象只拦截外部调用。内部调用不会经过代理,导致 AOP 失效。解决方法:

@Autowired
private MyService self;

public void outerMethod() {
    self.innerMethod(); // 通过代理调用
}

Q3: AOP 为什么不能拦截构造器?

Spring AOP 只能拦截方法调用,不能拦截构造器。如需拦截构造器,需使用 AspectJ 的编译期织入。


✅ 七、总结

特性Spring AOP 实现
实现方式动态代理(JDK / CGLIB)
代理生成时机Bean 初始化后(postProcessAfterInitialization
通知类型Before、After、Around、AfterReturning、AfterThrowing
执行顺序按拦截器链顺序执行
限制仅支持方法拦截,不支持构造器、字段
代理失效场景方法非 public、self-invocation、未正确配置 AOP

🧩 八、完整流程图(简化版)

@EnableAspectJAutoProxy
 └── 导入 AspectJAutoProxyRegistrar
      └── 注册 AnnotationAwareAspectJAutoProxyCreator
           └── Bean 初始化时调用 postProcessAfterInitialization()
                └── 获取匹配的 Advisor
                     └── 创建代理对象(ProxyFactory)
                          ├── JDK 动态代理(接口)
                          └── CGLIB 代理(子类)
                               └── 方法调用时进入拦截器链
                                    └── 执行 Around -> Before -> 目标方法 -> After -> AfterReturning / AfterThrowing

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值