博客
关于我
死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象
阅读量:439 次
发布时间:2019-03-06

本文共 2398 字,大约阅读时间需要 7 分钟。

Spring AOP 自动代理过程详解

在学习 Spring AOP 的过程中,我们需要深入理解其自动代理机制。Spring AOP 的核心是通过动态代理实现方法拦截和方法替换,这一过程主要由 AbstractAutoProxyCreator 类负责。在前面的文章中,我们分析了自动代理的入口和筛选Advisor的过程。本文将深入探讨如何为目标Bean创建代理对象。


创建代理对象的流程

AbstractAutoProxyCreator 类的 wrapIfNecessary 方法中,代理对象的创建主要分为以下几个步骤:

  • 检查是否需要代理

    首先,判断当前Bean是否需要代理。如果Bean已经被代理过(targetSourcedBeans 中存在)或不需要代理(advisedBeans 中标记为 false),则直接返回Bean。

  • 获取目标类

    如果需要代理,则获取目标Bean的类,并检查是否需要进行类代理(CGLIB动态代理)。默认情况下,proxyTargetClassfalse,表示优先使用JDK动态代理,但如果目标类没有实现可代理的接口,则会切换到CGLIB动态代理。

  • 获取适用的Advisor

    调用 getAdvicesAndAdvisorsForBean 方法,获取能够应用于目标Bean的所有Advisor。这些Advisor会根据 @Order 注解进行排序,优先级为:AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice

  • 创建代理对象

    如果有适用的Advisor,则通过 createProxy 方法创建代理对象。以下是具体的实现细节:


  • 代理工厂的创建

    代理对象的创建主要由 ProxyFactory 类负责。ProxyFactory 类的作用是创建动态代理对象,具体由 DefaultAopProxyFactory 实现。

    1. 选择代理类型

    DefaultAopProxyFactory 根据以下条件选择代理类型:

    • 如果 proxy-target-classfalse,优先使用JDK动态代理。如果目标类没有实现可代理的接口,则切换到CGLIB动态代理。
    • 如果 proxy-target-classtrue,优先使用CGLIB动态代理。如果目标类本身是一个接口,则仍使用JDK动态代理。

    2. 创建动态代理

    JdkDynamicAopProxyObjenesisCglibAopProxy 是两种主要的动态代理实现类。

    JDK动态代理(JdkDynamicAopProxy)

    • 实现JdkDynamicAopProxy 实现了 InvocationHandler 接口,通过 Proxy.newProxyInstance 方法创建代理对象。
    • 特点:无需修改目标类,直接通过拦截方法调用目标对象的方法。拦截器由 DynamicAdvisedInterceptor 实现。

    CGLIB动态代理(ObjenesisCglibAopProxy)

    • 实现ObjenesisCglibAopProxy 通过 Enhancer 创建代理类。CGLIB会生成目标类的超类,避免直接修改目标类。
    • 特点:支持通过构造器实例化代理对象,适用于一些特殊场景,如序列化、远程调用等。

    动态代理的实现细节

    1. InvocationHandler 的实现

    无论是JDK动态代理还是CGLIB动态代理,代理对象都实现了 InvocationHandler 接口,用于拦截目标对象的方法调用。拦截器的逻辑主要集中在以下几个方面:

    • 方法拦截:根据Advisor的配置,决定是否执行目标方法或替换目标方法。
    • 返回值处理:对目标方法的返回结果进行加工,例如在 equalshashCode 方法中添加代理对象的信息。

    2. Callback 的配置

    在CGLIB动态代理中,Callback 数组用于定义方法拦截器的逻辑。具体来说,Callback 的类型和顺序决定了拦截器的行为。以下是常见的 Callback 类型:

    • AOP_PROXY:进行AOP代理的通用拦截器。
    • INVOKETARGET:执行目标方法。
    • NO_OVERRIDE:空的 Callback,用于不需要拦截的方法(如 finalize())。
    • DISPATCH_TARGET:目标对象调度器,用于获取目标对象。
    • DISPATCH_ADVISED:配置管理器的调度器,用于执行 AdvisedSupport 的方法。

    总结

    Spring AOP 的自动代理过程可以分为以下几个关键步骤:

  • 筛选Advisor:通过 ClassFilterMethodMatcher 确定哪些Advisor适用于目标Bean。
  • 创建代理对象:根据选择的动态代理类型(JDK或CGLIB),通过 ProxyFactory 创建代理对象。
  • 配置代理工厂:设置目标类来源、Advisor数组以及拦截器逻辑。
  • 其中,CGLIB动态代理的实现相对复杂,涉及 Objenesis 库的实例化和 Callback 的配置。以下是两种动态代理的主要区别:

    • JDK动态代理:简单易用,适用于大多数场景。
    • CGLIB动态代理:适用于需要通过构造器实例化代理对象或对性能有特殊要求的情况。

    通过本文的分析,我们可以清晰地看到Spring AOP如何在背后为Bean创建代理对象,从而实现AOP的功能。如果需要进一步理解动态代理的实现细节,可以继续阅读下一篇文章,探讨 DynamicAdvisedInterceptor 拦截器的工作原理。

    转载地址:http://gksyz.baihongyu.com/

    你可能感兴趣的文章
    OpenMMLab | 【全网首发】Llama 3 微调项目实践与教程(XTuner 版)
    查看>>
    OpenMMLab | 不是吧?这么好用的开源标注工具,竟然还有人不知道…
    查看>>
    OpenMMLab | 如何解决大模型长距离依赖问题?HiPPO 技术深度解析
    查看>>
    OpenMMLab | 面向多样应用需求,书生·浦语2.5开源超轻量、高性能多种参数版本
    查看>>
    OpenMP 线程互斥锁
    查看>>
    OpenMV入门教程(非常详细)从零基础入门到精通,看完这一篇就够了
    查看>>
    OpenObserve云原生可观测平台本地Docker部署与远程访问实战教程
    查看>>
    openoffice使用总结001---版本匹配问题unknown document format for file: E:\apache-tomcat-8.5.23\webapps\ZcnsDms\
    查看>>
    views
    查看>>
    OpenPPL PPQ量化(2):离线静态量化 源码剖析
    查看>>
    OpenPPL PPQ量化(3):量化计算图的加载和预处理 源码剖析
    查看>>
    OpenPPL PPQ量化(4):计算图的切分和调度 源码剖析
    查看>>
    OpenPPL PPQ量化(5):执行引擎 源码剖析
    查看>>
    openpyxl 模块的使用
    查看>>
    OpenResty & Nginx:详细对比与部署指南
    查看>>
    openresty 前端开发入门六之调试篇
    查看>>
    OpenResty(nginx扩展)实现防cc攻击
    查看>>
    openresty完美替代nginx
    查看>>
    Openresty框架入门详解
    查看>>
    OpenResty(1):openresty介绍
    查看>>