该系列文章只是记录我学习源码时总结的一个思路,没有详细的实现代码。如果你觉得有帮助,请点个赞鼓励一下。
文章目录
入口
// reader 是根据配置文件的路径读取出的字节流
SqlSessionFactory sessionFactory= new SqlSessionFactoryBuilder().build(reader);
目的: build方法中委托XMLConfigBuilder解析配置文件,生成Configuration对象,复制给DefaultSqlSessionFactory的Configuration属性字段。
DefaultSqlSessionFactory是 SqlSessionFactory接口的默认实现
引入问题:XMLConfigBuilder 是如何加载xml的?
对于XML文件本身技术上的加载和解析都委托给了XPathParser,最终使用的是JDK自带的xml解析器而不是三方件dom4j,底层使用了xpath方式进行节点解析。
class XMLConfigBuilder{
private XMLConfigBuilder(Reader reader,String environment,Properties props){
this(new XPAthParse(reader,true,props,new XMLMapperEntityResolver()),environment,props);
}
private XMLConfigBuilder(XPathParse parser,String environment,Properties props){
}
}
class XPathParse{
private Document document;
.......
public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) {
commonConstructor(validation, variables, entityResolver);
this.document = createDocument(new InputSource(reader));
}
}
解读XPathParse构造函数中的实参含义:
- reader: 字节流,会被处理成Document
- validation: 是否进行DTD校验
- props: 实参中传递的配置项,解析XML中的Properties时会使用。
- XMLMapperEntityResolver: xml实体节点校验器,将线上dtd资源下载到本地项目中,使用key-value存储线上线下资源的对应关系,支持离线校验。
启示:方法实参类型和返回类型使用接口,而不用具体实现可以增强可拓展性
引入问题2: 具体是如何加载并解析xml的呢?
XPathParse 将字节流reader转成Document(dom)结构放在自身属性字段上
XMLConfigBuilder 将XpathParse放在自身的属性字段上
XMLConfifBuilder 的parse()开始正式解析Document 文件,返回Configuation
注意:文件只能解析一次
public Configuration parse() {
//如果已经解析过了,报错
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//根节点是configuration
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
针对每个节点的解析的具体实现都在方法parseConfiguration中
解析document发现
- properties: 来源有子节点,url/resource,实参(按顺序)
- setting:确保配置参数在Configuration中有setter方法,使用了MetaClass ,反射和外观设计模式
- typeAliases类型别名:将类型和别名以key-vlaue 的形式注册,当有Package,则遍历包下的class 注册
- PluginElement: 创建拦截器
- environment(主体):可以有多个environment(开发,测试等),使用不同的数据库需要创建不同的SqlSessionFactory实例,根据实参选择使用哪个环境,没有时则选择default
- dataSource 有type 属性,三种内建的数据源格式,也支持自定义。(UNPOOLED,POOLED,JNDI)