返回顶部
首页 > 资讯 > 后端开发 > Python >基于Spring整合mybatis的mapper生成过程
  • 754
分享到

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

Spring整合mybatis mapperSpring mybatis mappermybatis的mapper 2023-03-07 17:03:04 754人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录spring整合mybatis的mapper生成过程ClassPathMapperScanner#doScanClassPathBeanDefinitionScanner#doS

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一份

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: 基于Spring整合mybatis的mapper生成过程

本文链接: https://lsjlt.com/news/198906.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作