我的知识梳理-mybatis-spring源码阅读(1)

本文详细介绍了在Spring Boot环境中,Mybatis的自动配置过程,包括如何通过MybatisAutoConfiguration创建SqlSessionFactory和SqlSessionTemplate,以及MapperScannerConfigurer的注册和Mapper接口的实现。通过对源码的跟踪,揭示了Mybatis动态代理创建Mapper接口实现的原理,以及获取Spring Boot默认包路径的手段。

以下一个单元测试,普通的mybatis里的mapper查询

package club.wang.utils.cases.repository;

import club.wang.utils.BaseTest;
import club.wang.utils.cases.pojo.Cases;
import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

public class CaseRepositoryTest extends BaseTest {

    @Autowired
    private CaseRepository caseRepository;

    @Test
    public void findById() {
        Cases cases = caseRepository.findById(1L);
        System.out.println(JSON.toJSONString(cases));
    }
}

其中CaseRepository是一个mybatis的mapper接口,但是接口需要一个具体的实现类的对象才能进行实际的操作,熟悉mybatis的人应该知道,在运行期mybatis使用了动态代理给mapper接口创建了对应的实现类,并且实例化成一个bean以供注入,下面我们就从SpringApplication.run开始,一步一步的看一下一次查询是如何完成的

  • 因为用的Spring Boot和Mybatis Spring Boot Starter,所以根据starter的约定,找到自动配置类MybatisAutoConfiguration(此处还不知道spring-boot-starter的同学先去看一下,这里就不展开讲了)
  • MybatisAutoConfiguration中注册了两个主要的bean,一个是SqlSessionFactory,一个是SqlSessionTemplate;还创建了AutoConfiguredMapperScannerRegistrar用来发现注册MapperScannerConfigurer
  • 先来看SqlSessionFactory
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
...
}

代码太长,主要是根据yml或properties文件里的配置项通过SqlSessionFactoryBean来构建一个SqlSessionFactory,跟我们手写xml或者javaConfig类似,如果自动配置的东西和预想的不一样,就可以来个方法里查看具体哪里配置的和约定的不一致

  • 然后是sqlSessionTemplate
  @Bean
  @ConditionalOnMissingBean
  public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    ExecutorType executorType = this.properties.getExecutorType();
    if (executorType != null) {
      return new SqlSessionTemplate(sqlSessionFactory, executorType);
    } else {
      return new SqlSessionTemplate(sqlSessionFactory);
    }
  }

就是获取了配置的执行器类型来注册一个sqlSessionTemplate

  • 然后来看AutoConfiguredMapperScannerRegistrar
public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar {
}

@org.springframework.context.annotation.Configuration
@Import(AutoConfiguredMapperScannerRegistrar.class)
@ConditionalOnMissingBean({ MapperFactoryBean.class, MapperScannerConfigurer.class })
public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {
}

AutoConfiguredMapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,所以下面有一个额外的配置类用来Import它,并且这个配置类里面会打印一行日志
“Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer“
AutoConfiguredMapperScannerRegistrar还实现了BeanFactoryAware接口,可以通过setBeanFactory方法来获取到这个bean对应的beanFactory,然后在registerBeanDefinitions会通过beanFactory去获取默认的自动配置包路径,设置到MapperFactoryBean的basePackage字段里
不过这里感觉非常的绕,这里用一个静态类而不是使用一个@Bean方法来注册MapperFactoryBean主要是为了获取springBoot默认的包路径也就是

List<String> packages = AutoConfigurationPackages.get(this.beanFactory);

为了这一行代码,所以必须拿到beanFactory,简单翻了一下spring的源码查了一些资料,发现如果确实要拿默认配置的包路径也没什么别的更好的方法了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值