以下一个单元测试,普通的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的源码查了一些资料,发现如果确实要拿默认配置的包路径也没什么别的更好的方法了
本文详细介绍了在Spring Boot环境中,Mybatis的自动配置过程,包括如何通过MybatisAutoConfiguration创建SqlSessionFactory和SqlSessionTemplate,以及MapperScannerConfigurer的注册和Mapper接口的实现。通过对源码的跟踪,揭示了Mybatis动态代理创建Mapper接口实现的原理,以及获取Spring Boot默认包路径的手段。
473

被折叠的 条评论
为什么被折叠?



