mybatis3.5.x源码系列(1)

  1. 首先我们了解一下mybatis中的几个核心概念
  • Configuration 配置,可以理解为mybatis的大管家,管理一切
  • Environment 环境,这个主要负责数据源,事务管理器
  • MappedStatement mapper.xml对应的声明类,定义mapper中所有的标签,属性
  • Interceptor 拦截器,可以拦截Executor,ParameterHandler,ResultSetHandler,StatementHandler
  • SqlSessionFactory SQL会话管理工厂类
  • SqlSession SQL会话,定义了增,删,改,查,提交,回滚,获取java.sql.Connection,获取mapper
  • MapperProxy mapper代理类,生成接口代理对象
  • Executor 执行器,主要负责增,删,改,查,提交,回滚的执行
  • ParameterHandler 参数处理器,主要负责参数设置
  • ResultSetHandler 查询结果集处理器,用来封装ResultSet对应的结果
  • StatementHandler Statement处理器,用来执行Statement相应的操作

带着上面的概念,我们开始我们的源码分析入门之旅

  1. 首先我们要看看官方demo 打开mybatis-3-getting-started

例子:

代码结构:

1
2
3
4
5
6
7
8
9
10
11
src
main
test
java
io.jsbxyyx
mapper
Blog.java
BlogMapper.java
BlogMapper.xml
Demo.java
mybatis-config.xml

1
2
3
4
5
6
7
8
public static void main(String[] args) throws IOException {
String resource = "io/jsbxyyx/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
BlogMapper blogMapper = sqlSessionFactory.openSession().getMapper(BlogMapper.class);
Blog blog = blogMapper.selectBlog(1L);
System.out.println(blog);
}

XML创建SqlSessionFactory

1
2
3
4
org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String, java.util.Properties)
》org.apache.ibatis.builder.xml.XMLConfigBuilder#parse()
》org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration(org.apache.ibatis.parsing.XNode root)
》org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)

核心方法org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration

该方法会解析出properties,settings,typeAliases,plugins,objectFactory,objectWrapperFactory,reflectorFactory,environments,databaseIdProvider,typeHandlers,mappers

解析mappers

1
2
3
4
// 这里解析mappers下的package标签,也就是包扫描,以及mapper标签
org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement(org.apache.ibatis.parsing.XNode parent)
》org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode
》org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement

解析mappers,创建MappedStatement并缓存到内存

打开session

1
2
3
4
5
6
7
8
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
》org.apache.ibatis.session.Configuration#getDefaultExecutorType()
》org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource(org.apache.ibatis.session.ExecutorType execType, org.apache.ibatis.session.TransactionIsolationLevel level, boolean autoCommit)
》org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#getTransactionFactoryFromEnvironment(org.apache.ibatis.mapping.Environment)
》org.apache.ibatis.transaction.TransactionFactory#newTransaction(javax.sql.DataSource, org.apache.ibatis.session.TransactionIsolationLevel, boolean)
》org.apache.ibatis.transaction.jdbc.JdbcTransaction#JdbcTransaction(javax.sql.DataSource, org.apache.ibatis.session.TransactionIsolationLevel, boolean)
》org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
》org.apache.ibatis.session.defaults.DefaultSqlSession#DefaultSqlSession(org.apache.ibatis.session.Configuration, org.apache.ibatis.executor.Executor, boolean)

流程

获取数据源 =》开启事务 =》获取执行器 =》创建SqlSession

获取Mapper

1
2
3
4
org.apache.ibatis.session.Configuration#getMapper(java.lang.Class<T>, org.apache.ibatis.session.SqlSession)
》org.apache.ibatis.binding.MapperRegistry#getMapper(java.lang.Class<T>, org.apache.ibatis.session.SqlSession)
》org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)
》java.lang.reflect.Proxy#newProxyInstance(java.lang.ClassLoader loader, java.lang.Class<?>[] interfaces, java.lang.reflect.InvocationHandler h)

流程

根据接口class =》创建JDK动态代理对象org.apache.ibatis.binding.MapperProxy(这就是为啥mybatis的mapper定义是接口的原因)

执行方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
io.jsbxyyx.mapper.BlogMapper#selectBlog
》org.apache.ibatis.binding.MapperProxy#invoke
》org.apache.ibatis.binding.MapperProxy#cachedInvoker
》org.apache.ibatis.binding.MapperMethod#MapperMethod(java.lang.Class<?> mapperInterface, java.lang.reflect.Method method, org.apache.ibatis.session.Configuration config)
》org.apache.ibatis.binding.MapperProxy.PlainMethodInvoker#invoke
》org.apache.ibatis.binding.MapperMethod#execute(org.apache.ibatis.session.SqlSession, java.lang.Object[] args)
》org.apache.ibatis.session.Configuration#getMappedStatement(java.lang.String statement)
》org.apache.ibatis.executor.Executor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
》org.apache.ibatis.executor.CachingExecutor#createCacheKey(org.apache.ibatis.mapping.MappedStatement, java.lang.Object parameterObject, org.apache.ibatis.session.RowBounds, org.apache.ibatis.mapping.BoundSql)
》org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
》org.apache.ibatis.executor.BaseExecutor#queryFromDatabase(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
》org.apache.ibatis.executor.SimpleExecutor#doQuery(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.mapping.BoundSql)
》org.apache.ibatis.executor.statement.RoutingStatementHandler#RoutingStatementHandler(org.apache.ibatis.executor.Executor, org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.mapping.BoundSql)
》org.apache.ibatis.session.Configuration#newParameterHandler(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.mapping.BoundSql)
》org.apache.ibatis.scripting.LanguageDriver#createParameterHandler
》org.apache.ibatis.plugin.InterceptorChain#pluginAll(parameterHandler)
》org.apache.ibatis.session.Configuration#newResultSetHandler(org.apache.ibatis.executor.Executor, org.apache.ibatis.mapping.MappedStatement, org.apache.ibatis.session.RowBounds, org.apache.ibatis.executor.parameter.ParameterHandler, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.mapping.BoundSql)
》org.apache.ibatis.executor.resultset.DefaultResultSetHandler
》org.apache.ibatis.plugin.InterceptorChain#pluginAll(resultSetHandler)
》org.apache.ibatis.plugin.InterceptorChain#pluginAll(statementHandler)
》org.apache.ibatis.executor.SimpleExecutor#prepareStatement(org.apache.ibatis.executor.statement.StatementHandler, org.apache.ibatis.logging.Log)
》org.apache.ibatis.transaction.Transaction#getConnection
》org.apache.ibatis.transaction.jdbc.JdbcTransaction#openConnection
》org.apache.ibatis.executor.statement.StatementHandler#query(java.sql.Statement, org.apache.ibatis.session.ResultHandler)
》java.sql.PreparedStatement#execute
》org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets(java.sql.Statement)

流程

动态代理MapperProxy =》创建MappedStatement缓存key =》获取Executor =》分别加载parameter,resultSet,statement插件 =》 获取java.sql.Connection =》获取java.sql.Statement =》执行sql =》处理结果集

流程结束。

期待下次更新咯。:-D