mybatis源码分析


mybatis源码分析:
分为3个阶段:
1.解析mybatis-config.xml,构建Configuration对象(入口)
2.根据Mapper接口生成代理对象
3.执行Mapper接口的方法,调用代理对象方法,根据接口全类名+方法名 找到 对应xml中namespace+id的sql语句,执行sql,将结果映射成返回的参数类型(反射+属性赋值)

1.解析mybatis-config.xml,构建Configuration对象(入口):
String resource = "mybaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
1.new XMLConfigBuilder(inputStream, environment, properties);//初始化Configuration对象,并创建XmlConfigBuilder对象
2.build(parser.parse());
1.parser.parse();
parseConfiguration(parser.evalNode("/configuration"));//从mybaits-config.xml主配置文件中拿根节点/configuration ,解析里面的子节点放入Configuration大对象中
解析节点:properties,settings,typeAliases,plugins,objectFactory,objectWrapperFactory,reflectorFactory,environments,databaseIdProvicer,typeHandlers,mappers
重点是properties,settings,typeAliaes,plugins,environments,typeHandlers,mappers
1.propertiesElement(root.evalNode("properties")):解析resource或url,不能同时写这两个选项.
configuration.setVariables(defaults);
2.Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
configuration.setVfsImpl(vfsImpl);
settingsElement(settings);//给configuration中的属性赋值,如configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true)); //cacheEnabled二级缓存的总开关,默认为true
3.typeAliasesElement(root.evalNode("typeAliases"));
configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage); //扫描@Alias注解
4.pluginElement(root.evalNode("plugins"));
configuration.addInterceptor(interceptorInstance); //InterceptorChain底层是采用ArrayList存interceptor拦截器,ArrayList是有序的先进先出

5.environmentsElement(root.evalNode("environments"));// 每个environment对应一个SqlSessionFactory
configuration.setEnvironment(environmentBuilder.build());//主要是dataSource数据源,事务管理transactionManager的配置 ,建造者模式
6.typeHandlerElement(root.evalNode("typeHandlers"));//数据库字段jdbcType与java属性javaType的 类型映射
typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
7.mapperElement(root.evalNode("mappers"));//解析mappers的配置文件,放入configuration。 //mappers中有两种方式定义子节点:1.package 2.mapper中配置resource/url/class 三选一
configuration.addMappers(mapperPackage);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();//重点
configurationElement(parser.evalNode("/mapper"));
builderAssistant.setCurrentNamespace(namespace);//命名空间,MapperBuilderAssistant来处理
cacheRefElement(context.evalNode("cache-ref"));//二级缓存的引用
cacheElement(context.evalNode("cache"));//二级缓存,<cache type="" eviction="" flushInterval="" size="" blocking="" readOnly="" />
parameterMapElement(context.evalNodes("/mapper/parameterMap"));//入参parameterMap
resultMapElements(context.evalNodes("/mapper/resultMap"));//返回参数resultMap
sqlElement(context.evalNodes("/mapper/sql"));//sql标签
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));//解析真正的增删改查语句
final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
statementParser.parseStatementNode();//一级缓存开关:在select标签中:useCache,flushCache 。 主键配置useGeneratedKeys,keyProperty 或 selectKey

2.build(parser.parse());
new DefaultSqlSessionFactory(config);//创建默认的DefaultSqlSessionFactory。


mybaits三个重要的类:XmlConfigBuilder,XmlMapperBuilder,XmlStatementBuilder
XmlConfigBuilder解析主配置文件Mybatis-config.xml; XmlMapperBuilder解析业务映射文件*Mapper.xml; XmlStatementBuilder解析增删改查语句

2.根据Mapper接口生成代理对象
SqlSession sqlSession = sqlSessionFactory.openSession();
new DefaultSqlSession(configuration, executor, autoCommit);//默认的executor为SimpleExecutor,默认自动提交autoCommit为false
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
configuration.<T>getMapper(type, this);
mapperRegistry.getMapper(type, sqlSession);
mapperProxyFactory.newInstance(sqlSession);
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

3.执行Mapper接口的方法,调用代理对象方法
List<User> users = mapper.queryList();
MapperProxy.invoke();
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);//根据command.getType()的类型,选择要执行的增删改查语句,以下以select为例
result = executeForMany(sqlSession, args);
result = sqlSession.<E>selectList(command.getName(), param);
return this.selectList(statement, parameter, RowBounds.DEFAULT);
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); //最终是调用Executor的query方法
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; //先从缓存中查询,如果有直接返回,如果没有就查数据库
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); //从缓存中查询
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);//从数据库查询
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);//Executor的实现类有SimpleExecutor,ReuseExecutor,BatchExecutor,默认是SimpleExecutor
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());//创建连接Connection,创建Statement/PrepareStatement,对参数进行赋值
Connection connection = getConnection(statementLog);//创建Connection
stmt = handler.prepare(connection, transaction.getTimeout());//创建Statement/PrepareStatement
handler.parameterize(stmt);//对参数进行赋值
return handler.<E>query(stmt, resultHandler);//获取sql,执行sql,处理结果集resultSet
String sql = boundSql.getSql();
statement.execute(sql);
return resultSetHandler.<E>handleResultSets(statement);


posted on 2019-03-11 15:24  sgyi06  阅读(149)  评论(0编辑  收藏  举报

导航