Mybatis 有两个核心配置,全局配置会影响 Mybatis 的执行;Mapper 配置定义了查询的 SQL,下面我们来看看 Mybatis 是如何加载配置文件的。
准备案例进行分析,主要示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static void main(String[] args) throws Exception { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder() .build(inputStream);
SqlSession sqlSession = sessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.selectUserById("101"); System.out.println("user = " + user); }
|
1. 构建 SqlSessionFactory 对象
构建 SqlSessionFactory 对象,其实是通过 SqlSessionFactoryBuilder 构建的,代码如下:
1 2
| SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder() .build(inputStream);
|
创建 SqlSessionFactoryBuilder 对象,然后使用建造者模式构建 SqlSessionFactory。建造者模式用于构建复杂对象,无需关注内部细节。

SqlSessionFactoryBuilder 中用来创建 SqlSessionFactory 对象的方法是 build(),build() 方法有 9 个重载,可以用不同的方法来创建 SqlSessionFactory 对象。SqlSessionFactory 对象默认是单例的。
SqlSessionFactoryBuilder#build() 核心代码(删减):
1 2 3 4 5 6 7
| public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); }
|
2. 创建 XMLConfigBuilder 对象
XMLConfigBuilder 对象是 BaseBuilder 的子类,用于解析全局配置文件。

BaseBuilder 主要处理解析工作,类图如上所示。主要的子类及解析功能如下:
XMLMapperBuilder
:解析 Mapper 映射器。
XMLStatementBuilder
:解析 select、update、insert、delete 标签里的 SQL 语句。
XMLScriptBuilder
:解析动态 SQL。
XMLConfigBuilder
:解析 mybatis-config.xml 配置文件 或 全局配置文件。
2.1 XMLConfigBuilder 初始化
上面的其他三个解析处理类将在后续执行流程中会提及,先看下 XMLConfigBuilder 对象在初始化时的处理。
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 27 28 29
| public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) { this(Configuration.class, inputStream, environment, props); }
public XMLConfigBuilder(Class<? extends Configuration> configClass, InputStream inputStream, String environment, Properties props) { this(configClass, new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props); }
private XMLConfigBuilder(Class<? extends Configuration> configClass, XPathParser parser, String environment, Properties props) { super(newConfig(configClass)); ErrorContext.instance().resource("SQL Mapper Configuration"); this.configuration.setVariables(props); this.parsed = false; this.environment = environment; this.parser = parser; }
|
2.1.1 XPathParser 初始化
XPathParser 实际上是 Mybatis 全局配置文件解析器。XPathParser#XPathParser() 核心代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public XPathParser(InputStream inputStream, boolean validation, Properties variables) { commonConstructor(validation, variables, null); this.document = createDocument(new InputSource(inputStream)); }
private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) { this.validation = validation; this.entityResolver = entityResolver; this.variables = variables; XPathFactory factory = XPathFactory.newInstance(); this.xpath = factory.newXPath(); }
|
2.1.2 Configuration 初始化
Configuration 初始化时,Configuration#Configuration() 构造函数代码如下:
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 27 28 29 30 31 32 33 34
| public Configuration() { typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class); typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class); typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class); typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class); typeAliasRegistry.registerAlias("FIFO", FifoCache.class); typeAliasRegistry.registerAlias("LRU", LruCache.class); typeAliasRegistry.registerAlias("SOFT", SoftCache.class); typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class); typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class); typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class); typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class); typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class); typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class); typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class); typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class); typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class); languageRegistry.register(RawLanguageDriver.class); }
|
Configuration 初始化完成类型别名的注册工作。
2.1.3 总结
通过上述的分析可以看到 XMLConfiguration 完成了 XML 文件的解析对应 XPathParser 和 Configuration 对象的初始化操作,下面来看下 parse() 方法到底是如何解析配置文件的。
2.2 配置文件解析
XMLConfiguration#parse() 方法具体解析配置文件,最终将配置文件解析成 Configuration 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); }
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration; }
|
解析全局配置文件 configuration 根标签下的内容,XMLConfiguration#parseConfiguration() 核心代码。
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
private void parseConfiguration(XNode root) { try { propertiesElement(root.evalNode("properties")); Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfsImpl(settings); loadCustomLogImpl(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginsElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings); environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlersElement(root.evalNode("typeHandlers")); mappersElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
|