springboot使用的是2.3.1
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
---------------------------------------
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
- 从MapperScan说起
创建数据源时会使用`@MapperScan`扫描相应包的路径
MapperScan中有`@Import(MapperScannerRegistrar.class)`
进入MapperScannerRegistrar
`MapperScannerRegistrar`实现`ImportBeanDefinitionRegistrar`和`ResourceLoaderAware`
观察`registerBeanDefinitions`中有一行代码
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
进入到MapperScannerConfigurer
MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware
其中实现了BeanDefinitionRegistryPostProcessor的方法postProcessBeanDefinitionRegistry用于注册Bean到Spring容器中
/**
* {@inheritDoc}
*
* @since 1.0.2
*/
@Override
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);
if (StringUtils.hasText(lazyInitialization)) {
scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization));
}
scanner.registerFilters();
scanner.scan(
StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
重要的是`ClassPathMapperScanner继承自`ClassPathBeanDefinitionScanner`
`ClassPathMapperScanner`的`scan()-->doScan()`调用`ClassPathBeanDefinitionScanner`的`doScan()`然后`ClassPathMapperScanner-->processBeanDefinitions()`用于创建`Set<BeanDefinitionHolder>`将bean定义信息注册到容器当中。
接口本身是没有类的,那么这里将**MapperFactoryBean**类通过processBeanDefinitions方法设置进来,最终所有的dao层接口类都是这个**MapperFactoryBean**
- 说一下MapperFactoryBean
所有的sql信息执行都会通过这个类getObject(),就是sqlSession获取mapper的代理类,也就是各个接口的代理。
当SpringBean容器初始化时候会调用到checkDaoConfig()。
getSqlSession().getMapper(this.mapperInterface);,通过接口获取Mapper(代理类),调用过程如下;
\- DefaultSqlSession.getMapper(Class<T> type),获取Mapper
\- Configuration.getMapper(Class<T> type, SqlSession sqlSession),从配置中获取
\- MapperRegistry.getMapper(Class<T> type, SqlSession sqlSession),从注册中心获取到实例化生成
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
\- mapperProxyFactory.newInstance(sqlSession);,通过反射工程生成MapperProxy
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
MapperProxy实现InvocationHandler,执行会调用invoke()-->final MapperMethod mapperMethod = cachedMapperMethod(method);
mapperMethod.execute(sqlSession, args);执行SQL语句,并返回结果(INSERT、UPDATE、DELETE、SELECT)
- 然后再从SqlSessionFactory说起
先创建SqlSessionFactoryBean例如SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
SqlSessionFactoryBean实现了InitializingBean,所以实现了`afterPropertiesSet`
this.sqlSessionFactory = buildSqlSessionFactory();
buildSqlSessionFactory最后一行
this.sqlSessionFactoryBuilder.build(targetConfiguration);
build方法
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
所以是使用DefaultSqlSessionFactory创建sqlSessionFactory
- 还有SqlSessionTemplate
调用构造方法
this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
实现代码
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
PersistenceExceptionTranslator exceptionTranslator) {
notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
notNull(executorType, "Property 'executorType' is required");
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class }, new SqlSessionInterceptor());
}
其中sqlSessionProxy是动态代理