博客
关于我
死磕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/

    你可能感兴趣的文章
    POWER ENGLISH (6) - MODEL
    查看>>
    power english (1) —— passion
    查看>>
    Power English (1) 原文
    查看>>
    power English (3)原文
    查看>>
    POWER ENGLISH(7)- repetition
    查看>>
    SpringBoot中集成SpringBatch详细解析与实战示例(CSV文件读取十万条数据进行业务处理后写入Mysql数据库)
    查看>>
    powerbi 一张表在另外一张表中出现的数量_PowerBi之初步学习笔记
    查看>>
    QGIS怎样设置简体中文以及新建可编辑的多边形的图层
    查看>>
    PowerBuilder 使用自定义事件触发键盘Enter事件
    查看>>
    PowerCreatorCMS UploadResourcePic 任意文件上传漏洞复现
    查看>>
    PowerDesigner 使用的一些技巧(转)
    查看>>
    QGIS在Windows上下载安装与建立空间数据库连接
    查看>>
    PowerDesigner165安装婆姐汉花教程
    查看>>
    PowerDesigner使用教程:设置注释、默认值属性
    查看>>
    PowerDesigner使用教程:不显示背景网格
    查看>>
    PowerDesigner使用教程:创建数据模型以及导出
    查看>>
    PowerDesigner使用教程:右侧工具栏显示/隐藏
    查看>>
    PowerDesigner使用教程:导出sql文件以及解决中文乱码问题
    查看>>
    PowerDesigner使用教程:时间字段设置
    查看>>
    PowerDesigner使用教程:给字段添加唯一约束
    查看>>