知其然要知其所以然,探索每一个知识点背后的意义,你知道的越多,你不知道的越多,一起学习,一起进步,如果文章感觉对您有用的话,关注、收藏、点赞,有困惑的地方请评论,我们一起交流!
一、MyBatis 启动加载环境配置流程图
二、流程详解与源码分析
1. 入口:SqlSessionFactoryBuilder.build()
-
作用 :读取配置文件流,初始化
XMLConfigBuilder
。 -
源码路径 :
org.apache.ibatis.session.SqlSessionFactoryBuilder
javapublic SqlSessionFactory build(Reader reader, String environment, Properties properties) { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); }
2. 解析全局配置:XMLConfigBuilder.parse()
-
源码路径 :
org.apache.batis.builder.xml.XMLConfigBuilder
-
关键方法 :
parse()
逐级解析配置文件节点:javapublic Configuration parse() { // 解析 <configuration> 根节点 parseConfiguration(parser.evalNode("/configuration")); return configuration; } private void parseConfiguration(XNode root) { // 依次解析各配置块 propertiesElement(root.evalNode("properties")); environmentsElement(root.evalNode("environments")); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); mapperElement(root.evalNode("mappers")); }
3. 解析环境配置(environments)
- 源码路径 :
XMLConfigBuilder.environmentsElement()
- 功能:加载数据源和事务管理器。
- 核心对象 :
Environment
:包含DataSource
和TransactionFactory
。TransactionFactory
:决定事务管理方式(JDBC/MANAGED)。
4. 解析类型别名(typeAliases)
- 源码路径 :
XMLConfigBuilder.typeAliasesElement()
- 功能 :注册 Java 类型别名(如
com.example.User
→User
)。 - 核心对象 :
TypeAliasRegistry
,内部维护Map<String, Class<?>>
。
5. 解析插件(plugins)
- 源码路径 :
XMLConfigBuilder.pluginElement()
- 功能:加载拦截器(如分页插件),构建拦截器链。
- 核心对象 :
InterceptorChain
:通过动态代理包装目标对象(如Executor
)。- 示例:
@Intercepts
注解定义拦截点。
6. 解析映射器(mappers)
-
源码路径 :
XMLConfigBuilder.mapperElement()
-
功能:加载 Mapper 接口或 XML 文件,绑定 SQL 语句。
-
关键分支逻辑 :
java// 处理 <mapper> 标签的不同配置方式 if (resource != null) { // 从类路径加载 XML 文件 InputStream inputStream = Resources.getResourceAsStream(resource); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, ...); mapperParser.parse(); } else if (url != null) { // 从 URL 加载 XML 文件 } else if (mapperClass != null) { // 注册 Mapper 接口 configuration.addMapper(mapperClass); }
7. 解析 Mapper XML:XMLMapperBuilder.parse()
-
源码路径 :
org.apache.ibatis.builder.xml.XMLMapperBuilder
-
关键逻辑 :
javapublic void parse() { // 解析 <mapper> 根节点 configurationElement(parser.evalNode("/mapper")); } private void configurationElement(XNode context) { // 解析命名空间 String namespace = context.getStringAttribute("namespace"); // 解析 <select>, <insert> 等 SQL 节点 buildStatementFromContext(context.evalNodes("select|insert|update|delete")); }
8. 绑定 Mapper 接口
-
源码路径 :
org.apache.ibatis.binding.MapperRegistry
-
核心方法 :
addMapper()
javapublic <T> void addMapper(Class<T> type) { MapperProxyFactory<T> proxyFactory = new MapperProxyFactory<>(type); knownMappers.put(type, proxyFactory); // 解析接口方法对应的 SQL 语句 MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); }
9. 生成 MappedStatement
-
源码路径 :
org.apache.ibatis.builder.MapperBuilderAssistant
-
核心逻辑 :将 XML 或注解中的 SQL 定义转换为
MappedStatement
。javapublic MappedStatement addMappedStatement( String id, SqlSource sqlSource, ...) { // 构建 MappedStatement 并注册到 Configuration MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, ...); MappedStatement statement = statementBuilder.build(); configuration.addMappedStatement(statement); return statement; }
10. 构建 SqlSessionFactory
-
最终产物 :
DefaultSqlSessionFactory
。 -
源码路径 :
SqlSessionFactoryBuilder.build()
javapublic SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
三、关键类图
plaintext
SqlSessionFactoryBuilder
│
└── build() → XMLConfigBuilder
│
└── parse() → Configuration
│
├── Environment
├── MappedStatement
├── TypeAliasRegistry
└── InterceptorChain
│
└── Plugin.wrap() → 动态代理对象
四、调试技巧
-
断点位置:
XMLConfigBuilder.parseConfiguration()
:跟踪全局配置解析。XMLMapperBuilder.parse()
:观察 Mapper XML 的加载过程。MapperRegistry.addMapper()
:分析 Mapper 接口的动态代理生成。
-
日志输出 : 在
mybatis-config.xml
中开启日志,查看配置加载细节:xml<configuration> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> </configuration>
五、总结
通过上述流程,MyBatis 完成了从配置文件到运行时对象的转换,核心在于:
- 全局配置中心 :
Configuration
对象存储所有配置信息。 - 动态代理机制 :
MapperProxy
实现接口方法与 SQL 的绑定。 - 插件扩展 :
InterceptorChain
支持功能增强(如分页、监控)。