健兼
mybatis执行流程分析
jianzhang

配置加载

通过 XMLConfigBuilder.parse 解析configuration.xmlmapper.xml 生成org.apache.ibatis.session.Configuration,生成 SqlSessionFactory

1
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
2
SqlSessionFactory var5;
3
try {
4
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
5
var5 = this.build(parser.parse());
6
} catch (Exception var14) {
7
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
8
} finally {
9
ErrorContext.instance().reset();
10
11
try {
12
reader.close();
13
} catch (IOException var13) {
14
}
15
16
}
17
18
return var5;
19
}
20
21
public SqlSessionFactory build(Configuration config) {
22
return new DefaultSqlSessionFactory(config);
23
}

在生成Configuration 的过程,通过XMLMapperBuilder.parse -> XMLStatementBuilder.parseStatementNode -> XMLLanguageDriver.createSqlSource -> XMLScriptBuilder.parseDynamicTags -> Configuration.addMappedStatement 解析sql语句标签,生成对应的MappedStatement 对象,以id 作为key 放在 Configuration 的mappedStatements的map 中。

mapper对象的注册

MapperScan 注解引入了 MapperScannerRegistrar 的bean

image-20211110152624776

MapperScannerRegistrar 实现了接口 ImportBeanDefinitionRegistrar.registerBeanDefinitions ,注册了MapperScannerConfigurer 的bean

1
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
2
public MapperScannerRegistrar() {
3
}
4
5
/** @deprecated */
6
@Deprecated
7
public void setResourceLoader(ResourceLoader resourceLoader) {
8
}
9
10
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
11
//处理注解 MapperScan
12
AnnotationAttributes mapperScanAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
13
if (mapperScanAttrs != null) {
14
this.registerBeanDefinitions(mapperScanAttrs, registry, generateBaseBeanName(importingClassMetadata, 0));
15
}
16
17
}
18
19
void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) {
20
//添加 MapperScannerConfigurer 的bean定义
21
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
22
23
List<String> basePackages = new ArrayList();
24
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("value")).filter(StringUtils::hasText).collect(Collectors.toList()));
25
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText).collect(Collectors.toList()));
26
basePackages.addAll((Collection)Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName).collect(Collectors.toList()));
27
String lazyInitialization = annoAttrs.getString("lazyInitialization");
28
if (StringUtils.hasText(lazyInitialization)) {
29
builder.addPropertyValue("lazyInitialization", lazyInitialization);
30
}
31
32
builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages));
33
registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
34
}
35
36
}

image-20211110154806612

MapperScannerConfigurer 实现了 BeanDefinitionRegistryPostProcessor 接口,扫描mapper 包

1
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
2
3
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
4
5
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
6
7
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n"));
8
}
9
}

ClassPathMapperScanner 覆盖了 ClassPathBeanDefinitionScannerdoScan 方法,扫描mapper接口并配置其生成bean的工厂bean

1
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
2
3
private Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class;
4
5
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
6
//父类逻辑
7
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
8
//自己的逻辑
9
this.processBeanDefinitions(beanDefinitions);
10
11
return beanDefinitions;
12
}
13
14
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
15
GenericBeanDefinition definition;
16
for(Iterator var3 = beanDefinitions.iterator(); var3.hasNext(); definition.setLazyInit(this.lazyInitialization)) {
17
BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next();
18
definition = (GenericBeanDefinition)holder.getBeanDefinition();
19
//mapper 接口类型
20
String beanClassName = definition.getBeanClassName();
21
//MapperFactoryBean 构造器的参数为 mapper 接口类型
22
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
23
//org.mybatis.spring.mapper.MapperFactoryBean
24
definition.setBeanClass(this.mapperFactoryBeanClass);
25
26
boolean explicitFactoryUsed = false;
27
//MapperScan中指定了SqlSessionTemplate,则explicitFactoryUsed = true
28
...
29
//如果没指定SqlSessionTemplate,则按类型注入SqlSessionTemplate
30
if (!explicitFactoryUsed) {
31
LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
32
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
33
}
34
35
}
36
}
37
}

image-20211111170030530

1
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
2
private Class<T> mapperInterface;
3
private boolean addToConfig = true;
4
5
public MapperFactoryBean() {
6
}
7
8
protected void checkDaoConfig() {
9
super.checkDaoConfig();
10
11
Configuration configuration = this.getSqlSession().getConfiguration();
12
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
13
//添加mapper 代理工厂
14
configuration.addMapper(this.mapperInterface);
15
}
16
17
}
18
19
//通过此方法实例工厂bean,传入要生成代理对象的接口
20
public MapperFactoryBean(Class<T> mapperInterface) {
21
this.mapperInterface = mapperInterface;
22
}
23
24
//通过sqlSession获取代理对象
25
public T getObject() throws Exception {
26
return this.getSqlSession().getMapper(this.mapperInterface);
27
}
28
29
public Class<T> getObjectType() {
30
return this.mapperInterface;
31
}
32
33
public boolean isSingleton() {
34
return true;
35
}
36
37
}

image-20211110164204151

checkDaoConfig 方法会在bean初始化后在afterPropertiesSet 里被调用,实际上是调用 MapperRegistry.addMapper ,添加代理工厂MapperProxyFactory

1
public <T> void addMapper(Class<T> type) {
2
3
this.knownMappers.put(type, new MapperProxyFactory(type));
4
5
}

MapperFactoryBean.getObject 调用 MapperRegistry.getMapper ,最后通过 MapperProxyFactory 创建MapperProxy

1
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
2
MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
3
4
return mapperProxyFactory.newInstance(sqlSession);
5
}

Mapper 接口的代理对象 MapperProxy ,通过 MapperMethod 调用 SqlSessionTemplate -> SqlSessionInterceptor -> sqlSession执行sql

1
public class MapperProxy<T> implements InvocationHandler, Serializable {
2
private final SqlSession sqlSession;
3
private final Class<T> mapperInterface;
4
private final Map<Method, MapperMethod> methodCache;
5
6
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
7
this.sqlSession = sqlSession;
8
this.mapperInterface = mapperInterface;
9
this.methodCache = methodCache;
10
}
11
12
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
13
14
MapperMethod mapperMethod = this.cachedMapperMethod(method);
15
return mapperMethod.execute(this.sqlSession, args);
16
}
17
18
private MapperMethod cachedMapperMethod(Method method) {
19
return (MapperMethod)this.methodCache.computeIfAbsent(method, (k) -> {
20
return new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration());
21
});
22
}
23
}
1
public class SqlSessionTemplate implements SqlSession, DisposableBean {
2
3
private class SqlSessionInterceptor implements InvocationHandler {
4
@Override
5
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
6
//如果有事务,则从事务管理器中获取SqlSession,否则由sqlSessionFactory开启新的SqlSession
7
SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,
8
SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
9
try {
10
//调用sqlSession对应方法
11
Object result = method.invoke(sqlSession, args);
12
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
13
//没有配置事务,则立即提交当前sql操作,否则由事务管理器处理事务
14
sqlSession.commit(true);
15
}
16
return result;
17
} catch (Throwable t) {
18
} finally {
19
if (sqlSession != null) {
20
//没有事务则立即关闭
21
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
22
}
23
}
24
}
25
}
26
}

image-20211111165335234

Sql 执行

1
public class DefaultSqlSession implements SqlSession {
2
3
@Override
4
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
5
try {
6
//根据key从configuration中获取sql语句配置对象
7
MappedStatement ms = configuration.getMappedStatement(statement);
8
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
9
} catch (Exception e) {
10
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
11
} finally {
12
ErrorContext.instance().reset();
13
}
14
}
15
16
}

image-20211112190831641

1
public class CachingExecutor implements Executor {
2
3
@Override
4
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
5
//替换${...}的变量 ,#{...} 解析成jdbc的语句参数,用问号占位
6
BoundSql boundSql = ms.getBoundSql(parameterObject);
7
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
8
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
9
}
10
11
}

image-20211112190917737

1
public class SimpleExecutor extends BaseExecutor {
2
3
@Override
4
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
5
Statement stmt = null;
6
try {
7
Configuration configuration = ms.getConfiguration();
8
//handler 中包含了ParameterHandler,ResultSetHandler
9
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
10
//获取数据库连接,返回jdbc的Statement,ParameterHandler 设置jdbc的sql参数
11
stmt = prepareStatement(handler, ms.getStatementLog());
12
//发送sql到数据库执行,ResultSetHandler解析sql结果转换成实体对象返回
13
return handler.<E>query(stmt, resultHandler);
14
} finally {
15
closeStatement(stmt);
16
}
17
}
18
19
}

image-20211112191256092

1
public class PreparedStatementHandler extends BaseStatementHandler {
2
@Override
3
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
4
PreparedStatement ps = (PreparedStatement) statement;
5
//发送到数据库执行sql
6
ps.execute();
7
//解析返回结果
8
return resultSetHandler.<E> handleResultSets(ps);
9
}
10
}

image-20211112191323057

目录