基于Spring整合mybatis的mapper生成过程

作者:asLightYouAre 时间:2022-01-11 03:49:26 

Spring整合mybatis的mapper生成过程

基于Spring整合mybatis的mapper生成过程

mapperScannerConfigurer实现了BeandifinitionRegistryPostProcessor

后置处理beanFactory时会调用其postProcessBeanDefinitionRegistry

基于Spring整合mybatis的mapper生成过程

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));
 }

基于Spring整合mybatis的mapper生成过程

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;
}

 基于Spring整合mybatis的mapper生成过程

如上在进行包扫描时,会调用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

基于Spring整合mybatis的mapper生成过程

mapperInterface是在MapperFactoryBean创建时,会调用有参构造创建实例,值是创建是

基于Spring整合mybatis的mapper生成过程

基于Spring整合mybatis的mapper生成过程

 构造方法参数的获取从mdb中

基于Spring整合mybatis的mapper生成过程

创建除了传入mapperInterface,还会在设置属性值时调用MapperFactoryBean的父类SqlSessionDaoSupport#setSqFactory 将mdb中的sqlsessionfactory传入其中

基于Spring整合mybatis的mapper生成过程

mdb的sqlsessionFactory信息来历

基于Spring整合mybatis的mapper生成过程

查看方法栈调用,可以看到在开始填充属性时会去mdb中判断是否有propertyValue,如果有就返回,这就是之前扫描mapper后ClassPathMapperScanner#processBeanDefinitions对mdb的一些设置

在创造service时,如果有@Autowire 注入mapper,在createBean时会调用getObject

mdb只有一份,可得sqlsessionfactory即只有一份,sqlsessionTemplate一个mapper一份

来源:https://blog.csdn.net/m0_47039719/article/details/123615798

标签:Spring,mybatis,mapper
0
投稿

猜你喜欢

  • Java接口默认方法带来的问题分析【二义性问题】

    2023-11-27 20:32:55
  • android 6.0 写入SD卡的权限申请实例讲解

    2023-07-27 03:12:37
  • Java中的OkHttp使用教程

    2023-08-10 19:30:59
  • SpringBoot整合freemarker实现代码生成器

    2023-07-17 20:31:08
  • Spark网站日志过滤分析实例讲解

    2021-06-08 12:59:24
  • 每日六道java新手入门面试题,通往自由的道路

    2023-11-13 16:22:29
  • Java文件操作实例详解

    2023-11-25 10:29:40
  • java 发送http和https请求的实例

    2023-11-29 12:46:52
  • 合并有序数组的实现(java与C语言)

    2023-08-16 13:45:40
  • spring boot微服务场景下apollo加载过程解析

    2022-05-20 13:55:32
  • Java中对象与C++中对象的放置安排的对比

    2022-05-31 15:07:18
  • Java面试题之基本语法(图解)

    2023-11-24 09:37:34
  • 深入分析Java内存区域的使用详解

    2023-09-25 23:21:29
  • Java ShutdownHook原理详解

    2023-11-10 21:30:36
  • SpringCloud实战之Zuul网关服务

    2023-01-30 11:33:53
  • Unity打开淘宝app并跳转到商品页面功能的实现方法

    2023-06-17 01:05:18
  • Android实现悬浮窗的简单方法实例

    2023-06-17 18:11:02
  • Java统计字符串中字符出现次数的方法示例

    2023-11-25 08:23:02
  • JAVA基于SnakeYAML实现解析与序列化YAML

    2023-11-26 06:14:44
  • Java中IO流文件读取、写入和复制的实例

    2023-08-12 03:23:29
  • asp之家 软件编程 m.aspxhome.com