Mybatis源码解析

MybatisAutoConfiguration或者MybatisPlusAutoConfiguration核心作用是初始化工厂类SqlSessionFactory,其中包含属性interceptors、MapperLocations、TypeAliasesPackage、TypeEnumsPackage、TypeHandlers等。

MybatisAutoConfiguration自动装配类是由依赖:mybatis-spring-boot-starter【mybatis-spring-boot-autoconfigure】提供的,如果使用Mp版本则直接由MybatisPlusAutoConfiguration替代MybatisAutoConfiguration。


@Mapper通过@Import注解导入ImportBeanDefinitionRegistrar类型的实现类MapperScannerRegistrar,类ImportBeanDefinitionRegistrar的作用:

  1. 核心是引入类MapperScannerConfigurer,初始化其对应的BeanDefinition,并注册至IOC中BeanDefinition类型的注册表中。
  2. MapperScannerConfigurer实为BeanDefinitionRegistryPostProcessor类型的后置处理器。
  3. 注解@MapperScan相关属性value重置到MapperScannerConfigurer对应的BeanDefinition内部。
  4. 将MapperScannerConfigurer对应的BeanDefinition注册至Spring IOC容器内部。

BeanDefinitionRegistryPostProcessor类型的后置处理器MapperScannerConfigurer:此时@Mapper注解相关属性重置于MapperScannerConfigurer

  1. 扫描basePackages路径下全部的Mapper接口。
  2. 遍历每一个接口为其生成BeanDefinition,其内部beanClass属性value为MapperFactoryBean
  3. 将@Mapper组合注解相关属性转化为MapperFactoryBean相关字段或者方法属性。

@Mapper -> MapperScannerRegistrar -> MapperScannerConfigurer-> MapperFactoryBean转化流程:

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar{public void registerBeanDefinitions(AnnotationAttributes annoAttrs,BeanDefinitionRegistry registry, String beanName) {BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);...// 将 @MapperScan 属性sqlSessionTemplateRef 作为 MapperScannerConfigurer的属性sqlSessionTemplateRefString sqlSessionTemplateRef = annoAttrs.getString("sqlSessionTemplateRef");if (StringUtils.hasText(sqlSessionTemplateRef)) {builder.addPropertyValue("sqlSessionTemplateBeanName",annoAttrs.getString("sqlSessionTemplateRef"));}// 将 @MapperScan 属性sqlSessionFactoryRef 作为 MapperScannerConfigurer的属性sqlSessionFactoryBeanNameString sqlSessionFactoryRef = annoAttrs.getString("sqlSessionFactoryRef");if (StringUtils.hasText(sqlSessionFactoryRef)) {builder.addPropertyValue("sqlSessionFactoryBeanName",annoAttrs.getString("sqlSessionFactoryRef"));}...registry.registerBeanDefinition(beanName, builder.getBeanDefinition());}
}

以上将注解@MapperScan 属性转移到MapperScannerConfigurer。

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean{private boolean addToConfig = true;private SqlSessionFactory sqlSessionFactory;private SqlSessionTemplate sqlSessionTemplate;private String sqlSessionFactoryBeanName;private String sqlSessionTemplateBeanName;public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);//以下将 @MapperScan 相关属性转移到 ClassPathMapperScannerscanner.setAddToConfig(this.addToConfig);scanner.setAnnotationClass(this.annotationClass);scanner.setMarkerInterface(this.markerInterface);scanner.setSqlSessionFactory(this.sqlSessionFactory);scanner.setSqlSessionTemplate(this.sqlSessionTemplate);scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);scanner.setResourceLoader(this.applicationContext);scanner.setBeanNameGenerator(this.nameGenerator);scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);scanner.registerFilters();scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage,",; \t\n"));}
}

 将 MapperScannerConfigurer 相关属性转移到类ClassPathMapperScanner。

public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {private Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class;private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {GenericBeanDefinition definition;for (BeanDefinitionHolder holder : beanDefinitions) {//basePackages路径下扫描得到全部Mapper接口...// 将 Mapper接口之 GenericBeanDefinition 的BeanClass属性为 MapperFactoryBeandefinition.setBeanClass(this.mapperFactoryBeanClass);// 给 MapperFactoryBean 添加属性字段 addToConfigdefinition.getPropertyValues().add("addToConfig", this.addToConfig);boolean explicitFactoryUsed = false;// 给 MapperFactoryBean 添加属性字段 sqlSessionFactoryif (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {definition.getPropertyValues().add("sqlSessionFactory",new RuntimeBeanReference(this.sqlSessionFactoryBeanName));explicitFactoryUsed = true;} else if (this.sqlSessionFactory != null) {definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);explicitFactoryUsed = true;}// 给 MapperFactoryBean 添加属性字段 sqlSessionTemplateif (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {definition.getPropertyValues().add("sqlSessionTemplate",new RuntimeBeanReference(this.sqlSessionTemplateBeanName));explicitFactoryUsed = true;} else if (this.sqlSessionTemplate != null) {definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);explicitFactoryUsed = true;}definition.setLazyInit(lazyInitialization);}}
}

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

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

相关文章

聊天页面样式

聊天页面样式 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><link rel"styleshee…

C++程序员笔试训练

面试题1&#xff1a;使用库函数将数字转换位字符串 考点&#xff1a;c语言库函数中数字转换位字符串的使用 char *gcvt(double number, int ndigit, char *buf);参数说明&#xff1a; number&#xff1a;待转换的double类型数值。 ndigit&#xff1a;保留的小数位数。 buf&am…

数智教育创新如何向未来?腾讯云与你探索革新之路

引言 随着科技革命的快速发展&#xff0c;掀起教育领域的变革&#xff0c;新理念、新技术、新模式、新应用正不断涌现&#xff0c;正塑造着教育的未来形态。未来科技还将如何赋能教育创新&#xff1f; 5月31日&#xff0c;由腾讯云TVP 与西安电子科技大学联合举办的「数智教育的…

LC1020:飞地的数量

题目 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相邻&#xff08;上、下、左、右&#xff09;的陆地单元格或跨过 grid 的边界。 返回网格中 无法 在任意次数的移动…

Spark 面试题(十一)

1. 简述reduceByKey和groupByKey的区别和作用 &#xff1f; reduceByKey和groupByKey是Spark中的两种用于处理键值对&#xff08;Key-Value Pairs&#xff09;RDD的转换操作&#xff0c;它们在功能和性能上有一些关键的区别&#xff1a; groupByKey 作用&#xff1a;groupBy…

C++访问Private,Protecd的一些方法总结

前言 在编写C程序中 我们偶尔会碰到这样的三种特殊修改变量值的需求&#xff1a; [1]在不修改类原本的实现下&#xff0c;访问修改类的Private变量 [2]在不修改类原本的实现下&#xff0c;修改类的Protected变量 Private变量访问 public类模版函数特化 这种办法利用了类模…

springboot使用webscoket

springboot添加config配置项 package cn.lsy.api.yuy.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter;Configur…

CMS与AI的融合:构建万能表单小程序系统

引言&#xff1a; 随着人工智能技术的飞速发展&#xff0c;MyCMS作为一款功能强大的内容管理系统&#xff0c;通过集成AI技术&#xff0c;进一步拓展了其应用范围和智能化水平。本文将探讨如何利用MyCMS结合AI技术&#xff0c;构建一个能够将用户提交的万能表单数据转化为智能提…

helm命令如何修改values.yaml里面的变量值

在使用 Helm 安装 chart 的时候&#xff0c;你有几种方法可以在安装时修改 values.yaml 中的值&#xff0c;以便自定义安装。这些方法让你无需直接编辑 chart 包中原始的 values.yaml 文件&#xff1a; 1. 使用 --values 或 -f 参数指定自定义 values 文件 你可以创建一个自定…

【Ardiuno】实验使用ESP32单片机根据光线变化控制LED小灯开关(图文)

今天小飞鱼继续来实验ESP32的开发&#xff0c;这里使用关敏电阻来配合ESP32做一个我们平常接触比较多的根据光线变化开关灯的实验。当白天时有太阳光&#xff0c;则把小灯关闭&#xff1b;当光线不好或者黑天时&#xff0c;自动打开小灯。 int value;void setup() {pinMode(34…

前端老古董execCommand——操作 选中文本 样式

文章目录 ⭐前言⭐exe command api用法&#x1f496; example示例&#x1f496; 测试效果 ⭐execommand和getSelection 的联系⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于 前端老古董execCommand——操作选中文本。 execommand 当一个 HTML 文…

基于CentOS Stream 9平台安装Redis7.0.15

1. 官方下载地址 https://redis.io/downloads/#redis-downloads 1.1 下载或上传到/opt/coisini目录下&#xff1a; mkdir /opt/coisini cd /opt/coisini wget https://download.redis.io/releases/redis-7.0.15.tar.gz2. 解压 tar -zxvf redis-7.0.15.tar.gz 3. 创建软连接 或…

算法:分治(快排)题目练习

目录 题目一&#xff1a;颜色分类 题目二&#xff1a;排序数组 题目三&#xff1a;数组中的第k个最大元素 题目四&#xff1a;库存管理III 题目一&#xff1a;颜色分类 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地对它们进行排序&#xff0c;…

【回文 马拉车】214. 最短回文串

本文涉及知识点 回文 马拉车 LeetCode214. 最短回文串 给定一个字符串 s&#xff0c;你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。 示例 1&#xff1a; 输入&#xff1a;s “aacecaaa” 输出&#xff1a;“aaacecaaa” 示…

【单元测试】Spring Boot 的测试库

Spring Boot 的测试库 1.了解回归测试框架 JUnit2.了解 assertThat3.了解 Mockito4.了解 JSONPath5.测试的回滚 单元测试&#xff08;unit test&#xff09;是为了检验程序的正确性。一个单元可能是单个 程序、类、对象、方法 等&#xff0c;它是应用程序的最小可测试部件。 单…

[大模型]XVERSE-7B-chat Transformers 推理

XVERSE-7B-Chat为XVERSE-7B模型对齐后的版本。 XVERSE-7B 是由深圳元象科技自主研发的支持多语言的大语言模型&#xff08;Large Language Model&#xff09;&#xff0c;参数规模为 70 亿&#xff0c;主要特点如下&#xff1a; 模型结构&#xff1a;XVERSE-7B 使用主流 Deco…

用于每个平台的最佳WordPress LMS主题

你已选择在 WordPress 上构建学习管理系统 (LMS)了。恭喜&#xff01; 你甚至可能已经选择了要使用的 LMS 插件&#xff0c;这已经是成功的一半了。 现在是时候弄清楚哪个 WordPress LMS 主题要与你的插件配对。 我将解释 LMS 主题和插件之间的区别&#xff0c;以便你了解要…

如何打开pak文件-翻译pak语言包

最近碰到一些程序的语言包是pak格式&#xff0c;用Notepad打开全是乱码&#xff0c;百度搜索了一下&#xff0c;pak是一种少见的压缩文件格式&#xff0c;是pak Quake系列游戏所采用的一种特殊压缩包格式&#xff0c;由Quake游戏公司开发&#xff0c;用高版本的winrar可以打开&…

DP动态规划(下)

文章目录 如何在动态规划中有效地使用std::unordered_map?以下是使用std::unordered_map进行动态规划的一些关键点&#xff1a;选择合适的键&#xff1a;考虑哈希冲突&#xff1a;优化哈希函数&#xff1a; 下面是一个使用std::unordered_map解决斐波那契数列问题的例子&#…

测试 halcon算子 derivate_gauss 高斯一阶导数卷积

参上了 matlab fileexchange 有人上传了高斯 dx,dy一阶导卷积代码 卷积核的计算我修改成了核元素绝对值求做分母 归一化 和halcon的 derivate_gauss算子的计算结果对别如下 还是不知道怎么做到两者结果一致. 测试图像: 我的: halcon的: 获取两份图像的灰度值到数组并做对应位…