解析xml文件(简单版)
简述
本文是对mybatis解析xml文件的简单版,目的是为了能初步了解mybatis加载xml文件的过程.比如有一个mybatis-config.xml文件,里面是一些配置信息.当然还会有什么属性文件啦什么的,这些本文就先不考虑.
介绍过程
- 通过一个序列图,告诉你走完这个流程需要的关键类之间的调用关系,只是告诉你类之间的协调关系
- 贴出部分代码,告诉你方法之间的调用
- 建议通过代码和序列图结合看效果更好
序列图
- 上面的临时工就是一个方法里new出来的临时变量,完事后都没用了
- 配置文件中基本所有配置最后都放到了Configuration中,factory中一有个成员就是它,以后用到的mapper之类等等都从这里面取出来
下面,来拿出上面用到的大部分代码瞅瞅
结合源码分析
1.org.apache.ibatis.session.SqlSessionFactoryBuilder的builder方法用来接收用户的配置文件.进过多个调用,调用了下面这个代码(这个是其中一个,这里,为了走流程,就只弄出来一个)
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
//这个是个临时工,也可以说是个外包公司,把配置文件给它,接下来就说它
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
//调用它的解析方法,解析下,下面会说到,这个方法才是真正把配置文件放到Configuration中.
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
2.org.apache.ibatis.builder.xml.XMLConfigBuilder这个就是解析xml的,先看他的构造方法:
//这个方法是FacotryBuilder调用的其中一个,然后他们又调用下面那个
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
//这个new了一个XPathParser,用它来解析xml文件,下面就说这个XPathParser构造方法
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
//这个是上面的调用的,把上面new的parser,变成自己的一个成员
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());//调用super生成一个默认的Configuration
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
- org.apache.ibatis.parsing.XPathParser 这个类用来创建Document,然后它自带一些获取节点的方法供XMLConfigBuilder调用:
//构造方法
public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
//这个方法是用一个普通方法,伪装成通用的构造方法,供其他构造方法调用,这里就调用了,它的作用就是给这个类赋值
commonConstructor(validation, variables, entityResolver);
//创建用java的dom创建一个Document,这里就不说了,说白了就是java dom解析xml
this.document = createDocument(new InputSource(inputStream));
}
4.下面说一下XMLConfigBuilder中的parser() 方法,这个方法就是用上面生成的Document,把它里面的内容取出来放到Configuration中:
//调用了parseConfiguration方法
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//把Document中的东西取出来,放到configuration中
parseConfiguration(parser.evalNode("/configuration"));
//返回完工的configuration
return configuration;
}
//经过对xml的传来传去,各种解析,这里就按照mybatis想要的套路,给它取出来,放到configuration中
//
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(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);
}
}
5.经过上面的步骤,xml解析完了,处理完了,最后factorybuilder干了啥呢?就是这个:
//这个就是他干的事,new 了一个默认的facotry,给它一个成员configuration,然后返回给用户
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
以上就是最简单的mybatis加载xml文件的过程.如果有什么错误或疑问,可以留言给我.
Over!