mybaties是如何创建代理的

在SpringBoot集成MyBatis时,无需手动实现Mapper接口,Mybatis通过自动配置类MybatisAutoConfiguration生成SqlSessionFactory。MapperScannerRegistrar在扫描基包时,将Mapper接口的beanClass指向MapperFactoryBean。MapperFactoryBean继承SqlSessionDaoSupport,使用SqlSessionTemplate创建代理SqlSession执行SQL。当Service依赖Mapper时,Spring会调用MapperFactoryBean的getMapper方法,通过动态代理创建Mapper的代理对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:mapper层和我们平时说的dao层指的是同一个内容,都是数据库操作的封装,但是在没有集成mybatis时,dao层的接口都是需要我们手动去写其实现类,可在springboot集成中我们却发现:我们并没有手动去实现Mapper接口,但工程却能实实在在的查询数据库,获取我们需要的数据,那么问题来了,mybatis是何时、何地、如何生成mapper代理实例的呢?
在这里插入图片描述

Mybatis的自动配置类:MybatisAutoConfiguration,MybatisAutoConfiguration会被当做配置类被spring解析,我们来看看spring容器会从此配置类中解析到什么
    在这里插入图片描述
  @ConditionalOnClass:当classpath类路径下有指定类的条件下进行实例化。
  @ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
  @ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)  
在这里插入图片描述

在这里插入图片描述

可以看到,MybatisAutoConfiguration创建了SqlSessionFactory实例(实际类型:DefaultSqlSessionFactory),并注册到了spring容器;此时我们应该还注意到方法实例化MapperScannerRegistrarNotFoundConfiguration类中@Import({ AutoConfiguredMapperScannerRegistrar.class }),这里
AutoConfiguredMapperScannerRegistrar继承了ImportBeanDefinitionRegistrar(关于该类可以看下这篇文章Spring Boot通过ImportBeanDefinitionRegistrar动态注入Bean),那么它的registerBeanDefinitions方法也会被调用

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   

  logger.debug("Searching for mappers annotated with @Mapper");

  ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

  try {
   
    if (this.resourceLoader != null) {
   
      scanner.setResourceLoader(this.resourceLoader);
    }

    // 获取启动类所在的包,如:com.lee.shiro,会作为扫描开始的base package,一般只会有一个,但支持多个
    List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
    if (logger.isDebugEnabled()) {
   
      for (String pkg : packages) {
   
        logger.debug("Using auto-configuration base package '{}'", pkg);
      }
    }

    scanner.setAnnotationClass(Mapper.class);                    // 设置扫谁,Mapper注解是被扫描对象
    scanner.registerFilters();
    scanner.doScan(StringUtils.toStringArray(packages));        // 扫描所有mapper,进行bean定义处理
  } catch (IllegalStateException ex) {
   
    logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
  }
}



其中doScan方法会调用父类ClassPathBeanDefinitionScanner的doScan方法

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
		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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值