基于Spring整合mybatis的mapper生成过程
作者:asLightYouAre 发布时间:2022-01-11 03:49:26
Spring整合mybatis的mapper生成过程
mapperScannerConfigurer实现了BeandifinitionRegistryPostProcessor
后置处理beanFactory时会调用其postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.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();
//扫描包集合,注册mapper的beandifinition
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
ClassPathMapperScanner#doScan
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
if (beanDefinitions.isEmpty()) {
LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
} else {
//会对bean信息进行一些更改和添加,如设置propertyValues,向其中添加sqlsessionFactory等属性信息等
processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}
ClassPathBeanDefinitionScanner#doScan
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//遍历集合扫描包,获取包下的可用的mapper信息
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
如上在进行包扫描时,会调用ClassPathBeanDefinitionScanner#doScan,进行beanDefinition的扫描和注册
执行完后调用ClassPathMapperScanner#processBeanDefinitions
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
//有省略部分
//这里有遍历所有mapper
//将所有mapper的beanClass改为了mapperFactoryBean,最后生成的bean也是该类型的,只有在用到的
//时候才会调用getObject生成mapper
definition.setBeanClass(this.mapperFactoryBeanClass);
//接下来是添加一些MapperFactoryBean的属性信息到beandefinition里,在生成实例的时候,会根据
//此处传入的值来进行具体设置,如sqlsessionFactory
definition.getPropertyValues().add("addToConfig", this.addToConfig);
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
}
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
} else if (this.sqlSessionTemplate != null) {
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
}
}
确定了所有的mapper的beanDefinition为MapperFactoryBean类型后,
确定在生成的bean皆为MapperFactoryBean,在getBean时会调用MapperFactoryBean#getObject
mapperInterface是在MapperFactoryBean创建时,会调用有参构造创建实例,值是创建是
构造方法参数的获取从mdb中
创建除了传入mapperInterface,还会在设置属性值时调用MapperFactoryBean的父类SqlSessionDaoSupport#setSqFactory 将mdb中的sqlsessionfactory传入其中
mdb的sqlsessionFactory信息来历
查看方法栈调用,可以看到在开始填充属性时会去mdb中判断是否有propertyValue,如果有就返回,这就是之前扫描mapper后ClassPathMapperScanner#processBeanDefinitions对mdb的一些设置
在创造service时,如果有@Autowire 注入mapper,在createBean时会调用getObject
mdb只有一份,可得sqlsessionfactory即只有一份,sqlsessionTemplate一个mapper一份
来源:https://blog.csdn.net/m0_47039719/article/details/123615798


猜你喜欢
- 微信小程序 跳转页面小程序页面有2种跳转,可以在wxml页面或者js中:1,在wxml页面中: <navigator url=&quo
- 这篇文章主要介绍了SpringMVC的执行流程及组件详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- 前言上一节我们搭建起了服务注册中心,为各个服务提供者和消费者提供一个桥梁,这一节我们搭建一个服务提供者,注册到注册中心开源地址:https:
- 本文实例讲述了Android基于ListView实现类似Market分页加载效果。分享给大家供大家参考,具体如下:最近几天研究ListVie
- 存储访问框架,简称:SAF, 就是系统文件选择器+文件操作API。先选择文件,在用文件操作API处理文件。系统文件选择器,就和Windows
- 实现如下边框效果:虚线画效果,可以使用Android中的xml来做。下面话不多说,直接上代码:<RelativeLayout &nbs
- Excel知识点一、添加引用和命名空间添加Microsoft.Office.Interop.Excel引用,它的默认路径是C:\Progra
- 在之前文章的铺垫下,再为大家分享一篇:Android手势密码,附源码下载,不要错过。源码下载:http://xiazai.jb51.net/
- Java API不能远程访问HBase今天我在虚拟机里面安装了Hbase 1.2.4,说在windows上Java API调用访问下玩玩,结
- 本文实例为大家分享了flutter实现倒计时加载页面的具体代码,供大家参考,具体内容如下效果图实现步骤1、pubspec.yaml中添加依赖
- 喜欢另辟蹊径的我,在这里废话不多说了,直接上代码和图片了。效果图如下:第一步:MainActivity的代码如下:package net.l
- 在对类访问使用时,常用到的有访问类的成员、方法。实例化在对类进行访问时,需要将类进行实例化。并产生一个对象。可以使用关键字new来实现。由于
- pom.xml文件需要的内容<dependency> <groupId>re
- 一、可空类型修饰符(?)C#2.0里面实现了Nullable数据类型//A.比如下面一句,直接定义int为null是错误的,错误提示为无法将
- 本文实例讲述了Java编程实现统计一个字符串中各个字符出现次数的方法。分享给大家供大家参考,具体如下:import java.util.It
- 负载均衡使用微服务后,为了能够承担高并发的压力,同一个服务可能会启动多个实例。这时候消费者就需要负载均衡,把请求分散到各个实例。负载均衡主要
- 本文实例讲述了java实现mp3合并的方法。分享给大家供大家参考。具体实现方法如下:package test;import java.io.
- Android本地存储SharedPreferences详解存储位置SharedPreferences数据保存在: /data /data/
- 使用resilience4j的库和Spring Boot设计高弹性的微服务。微服务本质上是分布式的。当您使用分布式系统时,请始终记住这一第一
- RandomAccessFileRandomAccessFile 是随机访问文件(包括读/写)的类。它支持对文件随机访问的读取和写入,即我们