- 首先我们了解一下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相应的操作
带着上面的概念,我们开始我们的源码分析入门之旅
- 首先我们要看看官方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