版权声明:转载需声明本人出品 https://blog.csdn.net/weixin_40288381/article/details/88563838
流程图
SqlSessionFactory初始化流程:
- 创建SqlSessionFactoryBuilder对象,调用build方法,生成XmlConfigBuilder
- XmlConfigBuilder创建解析器parser
- 解析每一个标签把详细信息保存在Configuration中
- 解析mapper.xml;Mapper.xml中的每一个元素信息解析出来并保存在全局配置中,将增删查改的每一个标签每一个属性都解析出来,封装成一个MappedStatement–一个MappedStatement就代表一个增删查改标签的详细信息
- Configuration返回configuraion给XmlConfigBuilder
- XmlConfigBuilder调用build方法,传入configuraion去生成DefaultSqlSession
源码剖析
1.生成SqlSessionFactoryBuilder对象,调用build方法
//生成SqlSessionFactoryBuilder对象
//进入SqlSessionFactoryBuilder对象的build方法
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2.SqlSessionFactoryBuilder下的build方法下生成XmlConfigBuilder
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
//XmlConfigBuilder创建解析器parser
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//parser调用parse方法,返回结果为DefaultSqlSessionFactory(config),即默认SqlSessionFactory实现类为DefaultSqlSessionFactory,并传入后面会配置好的configuration
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
3.解析器调用parse方法
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//解析configuration标签,改标签为全局配置文件中的根标签
parseConfiguration(parser.evalNode("/configuration"));
//解析完标签信息后,返回已经保存了标签信息的configuraion
return configuration;
}
4.解析标签
解析配置文件下每个标签的详细信息并保存在configuraion中
//传入配置文件根标签
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectionFactoryElement(root.evalNode("reflectionFactory"));
settingsElement(root.evalNode("settings"));
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
//解析映射文件下的标签详细
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
解析映射文件中标签信息
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage);
} else {
//映射文件需要在全局配置文件下声明,声明路径可以使用resource或者url
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
InputStream inputStream = Resources.getUrlAsStream(url);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url == null && mapperClass != null) {
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
}
小结
创建SqlSessionFactory的默认实现为DefaultSqlSessionFactory,该方法需要传入Configuration实例。调用SqlSessionFactoryBuilder的build方法会对配置文件中标签进行解析并把详细信息保存在Configuration类,并返回Configuration实例给DefaultSqlSessionFactory,最终生成SqlSessionFactory。