主页 > 互联网  > 

SpringAOP源码解析

SpringAOP源码解析
前言

  Spring AOP(面向切面编程)是 Spring 框架的核心模块之一,其底层通过 动态代理 和 字节码增强 实现。以下是 Spring AOP 的源码解析,涵盖核心流程、关键类及实际应用场。

一、Spring AOP 的核心组件 核心接口 Joinpoint:表示程序执行的点(如方法调用、异常抛出),是切面的基础。Advice:切面的具体行为,分为: BeforeAdvice(前置通知)AfterAdvice(后置通知)AroundAdvice(环绕通知)ThrowsAdvice(异常通知) Pointcut:定义哪些 Joinpoint 需要被拦截(通过类和方法匹配规则)。Advisor:组合 Advice 和 Pointcut,表示一个完整的切面。 代理机制 Spring AOP 的代理分为两种: JDK 动态代理:基于接口的代理(要求目标类实现接口)。CGLIB 代理:基于子类继承的代理(无需接口,直接生成目标类的子类)。 二、源码解析:动态代理的创建 代理对象的生成入口 Spring AOP 的核心入口是 AopProxy 接口,其实现类为: JdkDynamicAopProxy(JDK 动态代理)CglibAopProxy(CGLIB 代理) 源码入口:DefaultAopProxyFactory#createAopProxy() public AopProxy createAopProxy(AdvisedSupport config) { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { // 选择 CGLIB 代理 return new CglibAopProxy(config); } else { // 选择 JDK 动态代理 return new JdkDynamicAopProxy(config); } } JDK 动态代理实现 关键类:JdkDynamicAopProxy 代理对象生成:通过 Proxy.newProxyInstance() 创建代理对象。方法拦截:实现 InvocationHandler 接口,重写 invoke() 方法。 源码示例: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 1. 获取目标方法和拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 2. 如果无拦截器,直接调用原方法 if (chain.isEmpty()) { return method.invoke(target, args); } // 3. 构建 MethodInvocation,执行拦截器链 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); return invocation.proceed(); } CGLIB 代理实现 关键类:CglibAopProxy 代理对象生成:通过 Enhancer 类生成目标类的子类。方法拦截:实现 MethodInterceptor 接口,重写 intercept() 方法。

源码示例:

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { // 1. 获取拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 2. 构建 CglibMethodInvocation,执行拦截器链 CglibMethodInvocation invocation = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy); return invocation.proceed(); } 三、拦截器链的执行流程 拦截器链的触发   无论是 JDK 动态代理还是 CGLIB 代理,最终都会调用 ReflectiveMethodInvocation#proceed() 方法,触发拦截器链的执行。

  源码入口:ReflectiveMethodInvocation#proceed()

public Object proceed() throws Throwable { // 1. 如果所有拦截器已执行,调用原始方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 2. 按顺序执行拦截器链 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) { MethodInterceptor mi = (MethodInterceptor) interceptorOrInterceptionAdvice; return mi.invoke(this); } else { // 动态匹配器处理 return ((InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice).interceptor.invoke(this); } } Advice 的链式调用 MethodInterceptor 的实现类(如 MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor)负责调用具体的 Advice。执行顺序: Around Advice → Before Advice → 目标方法 → Around Advice → After Advice → AfterReturning/AfterThrowing Advice。 四、实际应用中的关键点 定义切面 使用 @Aspect 注解定义切面,结合 @Pointcut 和 Advice 注解: @Aspect @Component public class LoggingAspect { @Pointcut("execution(* com.example.service.*.*(..))") public void serviceLayer() {} @Before("serviceLayer()") public void logBefore(JoinPoint joinPoint) { System.out.println("Method called: " + joinPoint.getSignature()); } } 配置代理模式 在 Spring Boot 中通过配置选择代理方式: # 强制使用 CGLIB 代理 spring.aop.proxy-target-class=true 调试 AOP 查看代理对象:注入的 Bean 如果是代理对象,类名会包含 $EnhancerBySpringCGLIB $ 或 $Proxy。日志输出:开启 Spring AOP 日志: logging.level.org.springframework.aop=DEBUG 五、源码设计亮点

责任链模式

拦截器链(MethodInterceptor)通过责任链模式实现,支持多个 Advice 的链式调用。

适配器模式

将不同类型的 Advice(如 BeforeAdvice、AfterAdvice)适配为统一的 MethodInterceptor 接口: MethodBeforeAdviceAdapter 将 MethodBeforeAdvice 适配为 MethodBeforeAdviceInterceptor。

动态匹配

通过 Pointcut 动态匹配方法,减少不必要的代理逻辑。 六、常见问题与解决方案 代理失效问题 自调用问题:同类方法内部调用 @Aspect 方法不会触发代理(需通过 AopContext.currentProxy() 获取代理对象)。Bean 未被 Spring 管理:确保切面类被 Spring 扫描(添加 @Component 注解)。 性能优化 避免过于宽泛的 Pointcut(如 execution(* com.example….(…)))。优先使用 JDK 动态代理(CGLIB 生成子类可能更耗时)。 多切面执行顺序 通过 @Order 注解或实现 Ordered 接口控制切面优先级: @Aspect @Order(1) public class SecurityAspect { /* ... */ } 七、总结

  Spring AOP 通过动态代理和拦截器链机制实现切面编程,核心类包括 AopProxy、MethodInterceptor 和 ReflectiveMethodInvocation。理解源码中的责任链模式和适配器模式,有助于解决实际开发中的代理失效、性能优化等问题。对于复杂场景,可结合 AspectJ 实现编译时织入(如 @AspectJ 注解 + 编译插件)。

标签:

SpringAOP源码解析由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“SpringAOP源码解析