MyBatis源码 核心配置解析 properties元素
XMLConfigBuilder的parseConfiguration(XNode)方法,用于解析配置文件
XMLConfigBuilder的propertiesElement(XNode)方法,用于解析配置文件的properties标签。
private void propertiesElement(XNode context) throws Exception {
if (context != null) {
//1.读取 <property> 元素的内容
Properties defaults = context.getChildrenAsProperties();
String resource = context.getStringAttribute("resource");
String url = context.getStringAttribute("url");
//不能同时设置 resource 和 url 属性
if (resource != null && url != null) {
throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other.");
}
//2.读取外部属性文件中的内容
if (resource != null) {
defaults.putAll(Resources.getResourceAsProperties(resource));
} else if (url != null) {
defaults.putAll(Resources.getUrlAsProperties(url));
}
//3.读取创建 SqlSessionFactory 对象时,用户传入的 Properties 参数对象
Properties vars = configuration.getVariables();
if (vars != null) {
defaults.putAll(vars);
}
//将最终的结果存入Configuration和XPathParser
parser.setVariables(defaults);
configuration.setVariables(defaults);
/*
总结:
1.属性的读取顺序, property 元素先于外部属性文件先于 Properties 参数对象。后存入属性的将覆盖先前存入的同名属性。
因为:Properties 对象存入键值对时,键已存在,用新值覆盖旧值。
优先级:
Properties 参数对象 > 外部属性文件 > properties 元素
2.最终的结果存入了 Configuration 和 XPathParser
*/
}
}
解析 properties 元素时序图

官方对Properties的解释:

Properties的使用:
property元素
resource/url引用外部的properties文件
<properties resource="org/mybatis/example/jdbc.properties">
<property name="username" value="dev_user"/>
<property name="password" value="12345"/>
</properties>
#这是一个外部的 jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3307/micro_message
jdbc.username=root
jdbc.password=root
Properties参数对象
示例:
Properties properties = new Properties();
properties.setProperty("jdbc.username", "admin");
properties.setProperty("jdbc.password", "admin123");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader, properties);
创建 SqlSessionFactory 对象时,可以传入 Properties 参数对象。
public SqlSessionFactory build(Reader reader, Properties properties);
public SqlSessionFactory build(Reader reader, String environment, Properties properties);
public SqlSessionFactory build(InputStream inputStream, Properties properties);
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties);
配置文件中通过 ${} 使用属性
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
MyBatis 源码中与 properties 元素解析相关的几个对象的数据关系:
XMLConfigBuilder BaseBuilder
XPathParser
Configuration
注意:箭头在这里仅表示引用关系。

XNode

public String getStringAttribute(String name) {
return getStringAttribute(name, null);
}
public String getStringAttribute(String name, String def) {
String value = attributes.getProperty(name);
if (value == null) {
return def;
} else {
return value;
}
}
public Properties getChildrenAsProperties() {
Properties properties = new Properties();
for (XNode child : getChildren()) {
String name = child.getStringAttribute("name");
String value = child.getStringAttribute("value");
if (name != null && value != null) {
properties.setProperty(name, value);
}
}
return properties;
}
public List<XNode> getChildren() {
List<XNode> children = new ArrayList<>();
NodeList nodeList = node.getChildNodes();
if (nodeList != null) {
for (int i = 0, n = nodeList.getLength(); i < n; i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
children.add(new XNode(xpathParser, node, variables));
}
}
}
return children;
}

public XNode(XPathParser xpathParser, Node node, Properties variables) {
this.xpathParser = xpathParser;
this.node = node;
this.name = node.getNodeName();
this.variables = variables;
this.attributes = parseAttributes(node);
this.body = parseBody(node);
}
private Properties parseAttributes(Node n) {
Properties attributes = new Properties();
NamedNodeMap attributeNodes = n.getAttributes();
if (attributeNodes != null) {
for (int i = 0; i < attributeNodes.getLength(); i++) {
Node attribute = attributeNodes.item(i);
String value = PropertyParser.parse(attribute.getNodeValue(), variables);
attributes.put(attribute.getNodeName(), value);
}
}
return attributes;
}
private String parseBody(Node node) {
String data = getBodyData(node);
if (data == null) {
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
data = getBodyData(child);
if (data != null) {
break;
}
}
}
return data;
}
private String getBodyData(Node child) {
if (child.getNodeType() == Node.CDATA_SECTION_NODE
|| child.getNodeType() == Node.TEXT_NODE) {
String data = ((CharacterData) child).getData();
data = PropertyParser.parse(data, variables);
return data;
}
return null;
}
阅读源码 核心思想
修炼功法
按照功法修炼,可以不断突破瓶颈,提升实力。
无功法,难得道。
上层结构
界面,粒度,跟踪数据,这些都是在代码的细节上建造的上层知识结构,这种上层结构是理解和组织的产物,是处于缓慢消退的记忆,只有缓慢消退的记忆才具有价值。
概念性的东西:获取感性的认识,而非严格的定义。
功法残页1:粒度学习。
粒度由大到小才是一种合理的学习顺序。先了解下新类,再去关注新类中新方法的功能,再去关注新类中新方法的功能的实现。关注你需要了解的新类和需要了解的方法,不要看见一个新类,不看完它的方法不罢休。你一上来直奔新类新方法的功能的实现,结果整了一天看了2个方法。整个系统成千上万的方法,看到何年何月。而且没有上层建筑,你就会前学后忘。
目标1. 认识新类:先了解下新的类的基本作用。
目标2. 认识新类的新方法的功能:了解类的方法的功能
了解多个新方法的功能:先掌握认识的类的一个方法的功能,再了解需要了解的方法的功能。
目标3. 理解新方法的实现:认识类的方法的实现
举例:
系统十分复杂,我们通常不可能掌握每个细节。我们应该从大到小的分层次去认识这个复杂的系统。生活中,我们先知道了中国,然后才知道西安,然后知道了西安有个回民街,钟楼,大雁塔。系统中,类就是一个比较大的层次,而类的方法就是比较小的层次。
示例:
/*
分析:
读源码,必然遇到新的类,新的方法。
第1步,认识新类。了解这个类的基本作用。
第2步,认识新类的新方法的功能。大致的理解这个方法的作用,通过自己看实现或看别人的分析。
第3步,认识新类的新方法的实现。搞清楚这个方法的内部实现。
这个XNode中的构造方法涉及了新类:XPathParser Node XNode
认识新类:
1. XPathParser 通过XPath表达式解析xml文档的类。
2. Node 表示xml文档中节点的对象。
3. XNode MyBatis提供的对Node进行封装后对象。
认识新类的方法:XNode的构造方法
把传递的3个参数直接保存了起来。作为自己的状态。
进行处理,得到了3个处理结果,也保存了起来,作为自己的状态。
*/
public XNode(XPathParser xpathParser, Node node, Properties variables) {
this.xpathParser = xpathParser;
this.node = node;
this.name = node.getNodeName();
this.variables = variables;
this.attributes = parseAttributes(node);
this.body = parseBody(node);
}
功法残页2:跟踪数据
程序的核心就是数据,数据的处理逻辑和数据的存储,跟踪你关注的数据,你将会接触到系统内部与这个数据相关的新类和新方法,从而提升对系统的认识。对学习系统的的任务划分提供了一种方式。
这样将对把系统的学习拆分了。现在只需要了解这些与关注数据相关的新类和新方法,就能提升对系统的认识。而不是把一个新类的全部东西都学完也不一定能够提升对系统的认识。
示例:
MyBatis 中 build 方法的3个参数,reader environment properties,跟踪这3个数据。你将会对MyBatis系统有进一步的认识。
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
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.
}
}
}
功法残页3:系统界面
示例: MyBatis 在插件方面,为开发人员提供了哪些东西呢?
MyBatis 为插件提供了 plugins 元素 plugin 元素 property 元素 Interceptor 接口,那么可以认为这是 MyBatis 提供的插件相关的界面。提出界面这个概念,一是为了将系统内部实现和用户操作部分分开。二是为了提供一个角度去认识系统。
个人认为:系统给开发提供的东西叫做这个系统的接口,而用于某个目的一组相关的接口,把这些东西当作系统的提供给开发人员的相关界面。界面,对学习系统的的任务划分提供了一种方式,每次关注系统的一个界面,学习系统的这个界面,获得对系统的认识的提升。
<!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
MyBatis源码 核心配置解析 properties元素的更多相关文章
- MyBatis 源码分析 - 配置文件解析过程
* 本文速览 由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括.本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAl ...
- Spring mybatis源码篇章-XMLLanguageDriver解析sql包装为SqlSource
前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-MybatisDAO文件解析(二) 首先了解下sql mapper的动态sql语法 具体的动态sql的 ...
- mybatis源码核心代码
/** * mybatis源码测试类 * @param args * @throws IOException * @see org.apache.ibatis.session.Configuratio ...
- mybatis源码-原来resultMap解析完是这样
目录 1 两个基础类 1.1 列映射类ResultMapping 1.2 结果集映射类ResultMap 2. 解析 2.1 入口函数 2.2 解析流程 2.3 获取 id 2.4 解析结果集的类型 ...
- Mybatis源码解读-配置加载和Mapper的生成
问题 Mybatis四大对象的创建顺序? Mybatis插件的执行顺序? 工程创建 环境:Mybatis(3.5.9) mybatis-demo,参考官方文档 简单示例 这里只放出main方法的示例, ...
- MyBatis 源码分析——配置信息
MyBatis框架的启动前期需要加载相关的XML配置信息.从官网上我们可以了解到他具有十几个节点.其中笔者认为比较重要的节点是settings节点.properties节点.environments节 ...
- MyBatis 源码分析 - 映射文件解析过程
1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...
- Mybatis源码解读-SpringBoot中配置加载和Mapper的生成
本文mybatis-spring-boot探讨在springboot工程中mybatis相关对象的注册与加载. 建议先了解mybatis在spring中的使用和springboot自动装载机制,再看此 ...
- Mybatis源码解析-BoundSql
mybatis作为持久层,其操作数据库离不开sql语句.而BoundSql则是其保存Sql语句的对象 前提 针对mybatis的配置文件的节点解析,比如where/if/trim的节点解析可见文章Sp ...
随机推荐
- Salesforce - 建立轮循机制的潜在客户分配规则
客服中心经常会遇到由多个客服轮流分配接进来的订单,例如你有100个订单进入系统,你希望五个客服每人分配20个,也就是一种小组的轮换机制,常被称为“轮询” 这种循环分配规需要保证平均分配给客服新的订单记 ...
- linux-根目录添加内存
01,添加磁盘到服务器 02, 查看添加的内容 这个是新添加的 03, 创建新分区 [root@oracle01 ~]# fdisk /dev/sdb --格式化分析 Welcome ). Chang ...
- Windows10 64位部署odoo12开发环境
预装Windows10 64位家庭版电脑一台 2019年7月 安装Python,这里的版本选择上有个坑,不要装最新的Python 3.7.x,原因是odoo12依赖pillow 4.0.0库,而这个4 ...
- fiddler抓包-2-5分钟学会手机端抓包
前言 小伙伴们在前篇是否学会了简单的电脑web或其它软件抓包了呢?今天小编给大家带来的是fiddler设置手机代理抓手机端的数据包. 大致流程如下: 1.准备一台wifi功能正常的真机或虚拟机:2.设 ...
- 基于JRebel开发的MybatisPlus热加载插件
前言 前天项目中使用了mybatis-plus,但是搭配Jrebel开发项目时,发现修改mapper的xml,或者mapper方法中的注解,Jrebel并没有能够reload mapper.于是就有了 ...
- useEffect传入第二个参数陷入死循环
最近新项目刚上手,就用了react的hooks,之前也看过hooks的不少文章,只是还没实战实战. 业务场景1:需要在页面一开始时得到一个接口的返回值,取调用另一个接口. 我的思路是,先设置这个接口的 ...
- CountDownLatch 源码分析
CountDownLatch 源码分析: 1:CountDownLatch数据结构 成员变量 Sync类型对象 private final Sync sync; Sync是继承AQS的一个类,Coun ...
- WPF ResourceDictionary XAML资源 c#代码 获取与遍历
使用C#代码来获取XAML资源,除去正常的FindResource.而且是能查询到资源的对象. 说实话还是很麻烦的. 比如说我现在有一堆静态资源放在xaml的资源中,我想通过绑定的方式来获取. 好比是 ...
- 使用jedis操作redis常用方法
在redis入门及在商城案例中的使用中简单介绍了下使用jedis如何操作redis,但是其实方法是跟redis的操作大部分是相对应的.我这里做下记录 1.String类型操作 public class ...
- 【BZOJ4833】最小公倍佩尔数(min-max容斥)
[BZOJ4833]最小公倍佩尔数(min-max容斥) 题面 BZOJ 题解 首先考虑怎么求\(f(n)\),考虑递推这个东西 \((1+\sqrt 2)(e(n-1)+f(n-1)\sqrt 2) ...