Mybatis代理对象是如何生成的

news2024/11/13 9:28:35

 Mybatis源码解析 - mapper代理对象的生成,你有想过吗,我们讲到了mybatis操作数据库的流程:先创建SqlSessionFactory,然后创建SqlSession,然后再创建获取mapper代理对象,最后利用mapper代理对象完成数据库的操作;Mapper代理对象的创建,利用的是JDK的动态代理,InvocationHandler是MapperProxy,后续Mapper代理对象方法的执行都会先经过MapperProxy的invoke方法。

  但是,此时SqlSessionFactory的创建、SqlSession的创建以及mapper代理对象的获取都是我们手动操作的,实际应用中,mybatis往往也不会单独使用,绝大多数都是集成在spring中,也就是说我们无需手动去管理mybatis相关对象的生命周期,全部都由spring容器统一管理,那么spring是什么时候在哪创建的mybatis的相关对象的呢?尤其是mapper代理对象MapperProxy的创建

Springboot集成mybatis

  当springboot(其实还是spring)集成mybatis后,mybatis的对象是交给spring容器管理的,只会实例化一次,然后伴随着spring容器一直存在,直到spring容器销毁

  自动配置:MybatisAutoConfiguration

    Mybatis的自动配置类:MybatisAutoConfiguration,至于如何加载此类,可参考:spring-boot-2.0.3启动源码篇一 - SpringApplication构造方法

    MybatisAutoConfiguration会被当做配置类被spring解析,我们来看看spring容器会从此配置类中解析到什么

     创建了SqlSessionFactory实例(实际类型:DefaultSqlSessionFactory),并注册到了spring容器;此时我们应该还注意到

  @Import({ AutoConfiguredMapperScannerRegistrar.class })

    AutoConfiguredMapperScannerRegistrar继承了ImportBeanDefinitionRegistrar(注意看类注释,有兴许的可以更深入的研究下),那么它的registerBeanDefinitions也会被调用

 View Code

    以我们启动类所在的包(com.lee.shiro)为基包,扫描所有的mapper,然后修改所有mapper在spring容器中的bean定义,将mapper的beanClass全部指向了MapperFactoryBean

  mapper代理对象的创建:MapperFactoryBean

    MapperFactoryBean继承SqlSessionDaoSupport,SqlSessionDaoSupport有两个方法用来设置SqlSession

 View Code

    可以看到SqlSession的实际类型是:SqlSessionTemplate,SqlSessionTemplate在MybatisAutoConfiguration以@Bean方式创建的

    Spring在创建Service实例:UserServiceImpl的时候,发现依赖mapper(可能还有其他的实例依赖mapper),那么就会去spring容器获取mapper实例,没有则进行创建,然后注入进来(依赖注入);具体创建过程如下

 View Code  

    因为Spring在mapper扫描的时候,将所有mapper bean定义中的beanClass设置成了MapperFactoryBean(继承了FactoryBean),所以通过createBean方法创建的mapper实例实际上是MapperFactoryBean对象,然后通过

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    // isFactoryDereference方法判断name中是否有&字符
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    // 此时的beanInstance可能是一个普通bean,也可能是一个FactoryBean
    // 如果是一个FactoryBean,那么就用它创建想要的bean实例
    // 此if表示,如果beanInstance是普通bean,或者本来就想要FactoryBean实例,则直接返回beanInstance
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    // 此时表明beanInstance是一个FactoryBean,并且不是想要FactoryBean实例
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 通过FactoryBean实例创建我们想要的实例
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

    获取真正想要的bean实例,如果beanInstance是普通bean,或者本来就想要FactoryBean实例(beanName中有&),那么直接返回beanInstance,否则用FactoryBean实例来创建我们想要的实例对象。说回来就是会调用MapperFactoryBean的getObject()方法来获取Mapper的代理对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1308620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jmeter配置使用(mac)

前言 这篇文件就是一个笔记&#xff0c;非mac用户不用看了&#xff0c;我这是换了mac&#xff0c;要用jmeter的倒腾。 一、下载 二、使用步骤 1.解压 tgz格式的直接用tar命令就行 tar -zxvf 包名2.启动 一种是进入解压包的bin目录启动 这种方式启动的就是命令框不能关闭&am…

Python实现多种图像锐化方法:拉普拉斯算子和Sobel算子

Python实现多种图像锐化方法&#xff1a;拉普拉斯算子和Sobel算子 图像和视频逐渐成为人们生活中信息获取的重要来源&#xff0c;而图像和视频在传输过程中有很多因素可能造成图像模糊&#xff0c;比如不正确的聚焦会产生离焦模糊&#xff0c;景物和照相机的相对运动会造成运动…

(开源)2023工训大赛智能垃圾分类项目(可循环播放视频,显示垃圾分类信息,拍照识别,垃圾分类,满载报警,压缩)

省赛:由于这个比赛是两年一届&#xff0c;并未做足充分的准备&#xff0c;但是通过一定的单片机基础&#xff0c;加上速成能力&#xff0c;也就是熬夜学&#xff0c;通过疯狂的网络搜索&#xff0c;在省赛第5 入选国赛 下面来简单介绍一下我们作品&#xff1a; 主控&#xff1…

代码随想录算法训练营第二十四天(回溯算法篇)|理论基础

结束了二叉树的篇章&#xff0c;我们进入到回溯啦&#xff01; 学习资料&#xff1a;代码随想录 (programmercarl.com) 理论基础 回溯算法又称回溯搜算算法&#xff0c;是一种搜索方法。 作为递归的“副产品”&#xff0c;只要右递归的地方就会有对应的回溯的过程。 回溯算…

Git命令大全:从基础到高级应用

目录 一、增加/删除文件 1.1 添加文件到暂存区 1.2 添加所有文件到暂存区 1.3 从暂存区移除文件 1.4 从版本库和工作区删除文件 二、代码提交 2.1 提交暂存区文件到本地仓库 2.2 修改最后一次提交信息 三、本地分支 3.1 创建新分支 3.2 切换分支 3.3 创建并切换到新分支 3.4 删…

微信小程序:布局样式

效果 wxml <view class"layout"><view class"left"><view>1</view><view>1</view><view>1</view><view>1</view><view>1</view></view><view class"right"&…

计算机毕业设计 基于Web的城市旅游网站的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

发布jar包到maven中央仓库

1. 环境 在网上找的很多文章中写得都有很多问题&#xff0c;这里记录一下最近一次成功地发布jar包到maven中央仓库的过程。并附带上每一个步骤官方的指导链接。 系统&#xff1a;mac&#xff08;windows系统在下载辅助工具时不太一样&#xff0c;在配置上和mac系统没有区别&…

rk3568 RGMII KSZ8795 MAC TO MAC

RK3568与KSZ8795交换机芯片连接&#xff0c;直接MAC TO MAC方式&#xff0c;这样一下就扩展会4路网口&#xff0c;应该场合比较多&#xff0c;移植过程如下&#xff1a; 参考《Rockchip_Developer_Guide_Linux_MAC_TO_MAC_CN.pdf》 《rockchip RGMIImv88e6390 管理型交换机功…

【HarmonyOS】【DevEco Studio】安装教程及环境配置问题解决

目录 一、DevEco Studio 安装二、配置环境ohmp安装报错问题解决方法一&#xff1a;注册表删除数值&#xff08;没解决&#xff09;方法二&#xff1a;进入DevEco Studio点击Settings进入设置&#xff08;没解决&#xff09;方法三&#xff1a;自己去官网下载ohmp的包安装&#…

13.Spring 整合 Kafka + 发送系统通知 + 显示系统通知

目录 1.Spring 整合 Kafka 2.发送系统通知 2.1 封装事件对象 2.2 开发事件的生产者和消费者 2.3 触发事件&#xff1a;在评论、点赞、关注后通知​编辑 3.显示系统通知 3.1 通知列表 3.1.1 数据访问层 3.1.2 业务层 3.1.3 表现层 3.2 开发通知详情 3.2.1 开发数据…

mac安装pnpm与使用

1、什么是pnpm&#xff1f; pnpm 全称 performant npm&#xff0c;意思是高性能的 npm。pnpm 由 npm/yarn 衍生而来&#xff0c;解决了 npm/yarn 内部潜在的 bug&#xff0c;极大的优化了性能&#xff0c;扩展了使用场景。被誉为 “最先进的包管理工具”。 2、pnpm特点 速度…

Eolink Apikit 如何进行 Websocket 接口测试?

什么是 websocket &#xff1f; WebSocket 是 HTML5 下一种新的协议&#xff08;websocket协议本质上是一个基于 tcp 的协议&#xff09;。 它实现了浏览器与服务器全双工通信&#xff0c;能更好的节省服务器资源和带宽并达到实时通讯的目的 Websocket 是一个持久化的协议。…

限流常用算法以及基于Sentinel的微服务限流及熔断

一、服务限流的作用及实现 在没有任何保护机制的情况下&#xff0c;如果所有的流量都进入服务器&#xff0c;很可能造成服务器宕机导致整个系统不可用&#xff0c;从而造成巨大的损失。为了保证系统在这些场景中仍然能够稳定运行&#xff0c;就需要采取一定的系统保护策略&…

docker compose部署wordpress

准备机器&#xff1a; 192.168.58.151 &#xff08;关闭防火墙和selinux&#xff09; 安装好docker服务 &#xff08;详细参照&#xff1a;http://t.csdnimg.cn/usG0s 中的国内源安装docker&#xff09; 部署wordpress: 创建目录&#xff1a; [rootdocker ~]# mkdir…

【什么是POI,为什么它会导致内存溢出?】

什么是POI&#xff0c;为什么它会导致内存溢出 什么是POIExcel并没看到的那么小POI的溢出原理 拓展知识几种Workbook格式 什么是POI Apache POl&#xff0c;是一个非常流行的文档处理工具&#xff0c;通常大家会选择用它来处理Excel文件。但是在实际使用的时候经常会遇到内存溢…

VR汽车技术服务虚拟仿真实训平台更好地辅助职业上岗培训

VR汽车虚拟仿真教学软件是一种基于虚拟现实技术的教学辅助工具。它能够模拟真实的汽车环境和操作场景&#xff0c;让学生能够通过虚拟仿真来学习和实践汽车相关知识和技能。 与传统的教学方式相比&#xff0c;VR汽车虚拟仿真教学软件具有更高的视觉沉浸感和互动性&#xff0c;能…

网络时间服务器

本章主要介绍网络时间服务器。 使用chrony配置时间服务器 配置chrony客户端向服务器同步时间 1 时间同步的必要性 一些服务对时间要求非常严格&#xff0c;例如&#xff0c;图所示的由三台服务器搭建的ceph集群。 这三台服务器的时间必须保持一致&#xff0c;如果不一致&#…

https网站连接图标四种状态(安全、没有完全安全、过期和危险)

浏览 Web 时&#xff0c;地址栏中会显示一个图标&#xff0c;指示与要访问的网站的连接的安全性。 此图标可帮助您确定是否可以安全发送和接收网站的信息。 连接会告知发送到站点和从站点发送的信息&#xff08;如密码、地址或信用卡&#xff09;是否安全发送&#xff0c;且无法…

Linux环境下maven的安装

到官网下载maven 步入下面的地址选择合适的maven版本 https://dlcdn.apache.org/maven/ 以笔者为例&#xff0c;选择了3.5.4这个版本 将maven上传到Linux服务器并解压 tar -zxvf apache-maven-3.5.4-bin.tar.gz配置环境变量 我们使用vim编辑profile vim /etc/profile环境…