全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

Spring AOP原理

Spring AOP通过运行时动态代理实现横切关注点的分离。

核心概念

概念说明示例
Joinpoint连接点,程序执行的特定点方法调用、异常抛出
Pointcut切点,匹配连接点的表达式execution(* com.example..(..))
Advice通知,在切点执行的代码@Before、@After、@Around
Aspect切面,通知+切点的组合@Aspect标注的类
Weaving织入,将切面应用到目标对象运行时动态代理
Target目标对象,被代理的对象业务Bean

代理对象创建流程

Java
┌─────────────────────────────────────────────────────┐
│                  Spring容器启动                       │
└─────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────┐
│     AbstractAutoProxyCreator.postProcessAfterInitialization    │
│     (BeanPostProcessor的后置处理)                     │
└─────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────┐
│     查找匹配当前Bean的所有Advisor (切面增强器)        │
└─────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────┐
│     存在匹配的Advisor → 创建代理对象                  │
│     不存在 → 返回原始Bean                            │
└─────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────┐
│     选择代理方式:JDK动态代理 或 CGLIB               │
└─────────────────────────────────────────────────────┘

核心类解析

AnnotationAwareAspectJAutoProxyCreator

Java
// AOP核心处理器,实现BeanPostProcessor
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    // Bean初始化后创建代理
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.advisedBeans.containsKey(cacheKey)) {
                return bean;  // 已处理过
            }
            if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }

            // 查找匹配的Advisor
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(
                    bean.getClass(), beanName, specificTargetSource);

            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                // 创建代理对象
                Object proxy = createProxy(bean.getClass(), beanName,
                        specificInterceptors, specificTargetSource);
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            }
        }
        return bean;
    }
}

代理对象创建

Java
protected Object createProxy(Class<?> beanClass, String beanName,
        Object[] specificInterceptors, TargetSource targetSource) {

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    // 决定使用哪种代理方式
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        } else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    // 构建Advisor链
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);

    return proxyFactory.getProxy(getProxyClassLoader());
}

切点表达式解析

Java
// AspectJExpressionPointcut解析切点表达式
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
        implements ClassFilter, MethodMatcher {

    private PointcutParser pointcutParser;
    private PointcutExpression pointcutExpression;

    // 类匹配
    @Override
    public boolean matches(Class<?> targetClass) {
        return pointcutExpression.couldMatchJoinPointsInType(targetClass);
    }

    // 方法匹配
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
        return shadowMatch.alwaysMatches();
    }
}

通知执行链

Java
// ReflectiveMethodInvocation - 通知链式调用
public class ReflectiveMethodInvocation implements ProxyMethodInvocation {

    protected Object invokeJoinpoint() throws Throwable {
        // 执行目标方法
        return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
    }

    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);
    }
}

通知适配器

text
// 将不同类型通知适配为MethodInterceptor
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry {

    private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }
}

// @Before适配器示例
class MethodBeforeAdviceAdapter implements AdvisorAdapter {
    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }
}

要点总结

  • Spring AOP基于BeanPostProcessor在Bean初始化后创建代理
  • 代理方式由proxyTargetClass和接口情况共同决定
  • Pointcut表达式由AspectJ解析器处理
  • 通知通过责任链模式顺序执行
  • 五种通知最终都被适配为MethodInterceptor

📝 发现内容有误?点击此处直接编辑

← 上一篇 AOP实战案例
下一篇 → 多个切面执行顺序
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库