mybatis源码解析之Configuration加载(四)
概述
上一篇文章,我们主要讲了datasource的相关内容,那么<environments>标签下的内容就看的差不多了,今天就来看一下在拿到transationManager和datasource之后,mybatis又做了什么事情呢?
Environment类
我们先来看下解析<environments>标签的那段代码:
- private void environmentsElement(XNode context) throws Exception {
- if (context != null) {
- if (environment == null) {
- environment = context.getStringAttribute("default");
- }
- for (XNode child : context.getChildren()) {
- String id = child.getStringAttribute("id");
- if (isSpecifiedEnvironment(id)) {
- TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
- DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
- DataSource dataSource = dsFactory.getDataSource();
- Environment.Builder environmentBuilder = new Environment.Builder(id)
- .transactionFactory(txFactory)
- .dataSource(dataSource);
- configuration.setEnvironment(environmentBuilder.build());
- }
- }
- }
- }
我们看一下12-15行代码,12-14行主要就是创建了一个Environment.Builder类,将之前获取到的id,transationManager,datasource放进去,第15行代码,调用build方法获取environment对象,并将其放进configuation中。逻辑上很简单,但是写法上有点奇怪,一下子还不怎么看得懂,连续点了这么多的方法,我们来研究下这么写的好处?
首先我们来看下Environment类的内容:
- public final class Environment {
- private final String id;
- private final TransactionFactory transactionFactory;
- private final DataSource dataSource;
- public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
- if (id == null) {
- throw new IllegalArgumentException("Parameter 'id' must not be null");
- }
- if (transactionFactory == null) {
- throw new IllegalArgumentException("Parameter 'transactionFactory' must not be null");
- }
- this.id = id;
- if (dataSource == null) {
- throw new IllegalArgumentException("Parameter 'dataSource' must not be null");
- }
- this.transactionFactory = transactionFactory;
- this.dataSource = dataSource;
- }
- public static class Builder {
- private String id;
- private TransactionFactory transactionFactory;
- private DataSource dataSource;
- public Builder(String id) {
- this.id = id;
- }
- public Builder transactionFactory(TransactionFactory transactionFactory) {
- this.transactionFactory = transactionFactory;
- return this;
- }
- public Builder dataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- return this;
- }
- public String id() {
- return this.id;
- }
- public Environment build() {
- return new Environment(this.id, this.transactionFactory, this.dataSource);
- }
- }
- public String getId() {
- return this.id;
- }
- public TransactionFactory getTransactionFactory() {
- return this.transactionFactory;
- }
- public DataSource getDataSource() {
- return this.dataSource;
- }
- }
看第1行代码,这个类被final修饰,这个跟String等不可变类有点像,一旦创建了,就不能再改变了。
这个类有三个类变量,分别是 id,transationfactory,datasource,分别对应于配置文件中的三个配置项(id、transactionManager、DataSource),这几个我们之前已经分析过了,这个几个字段也分别被final修饰,一旦设置,就不能再修改,而且针对这几个字段,类里面只提供了get方法,没有set方法(反正也不能修改),只能够去获取配置设定的值,而不能修改。
在源码里面,我们看到这个类里面有一个静态内部类,Builder,内容如下:
- public static class Builder {
- private String id;
- private TransactionFactory transactionFactory;
- private DataSource dataSource;
- public Builder(String id) {
- this.id = id;
- }
- public Builder transactionFactory(TransactionFactory transactionFactory) {
- this.transactionFactory = transactionFactory;
- return this;
- }
- public Builder dataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- return this;
- }
- public String id() {
- return this.id;
- }
- public Environment build() {
- return new Environment(this.id, this.transactionFactory, this.dataSource);
- }
- }
这种写法熟悉设计模式的朋友肯定一眼就看出来了,这里使用了构造者模式,将创建Environment 对象的过程分了好几个步骤,先设置id,再设置transactionFactory,接着是dataSource,最后可以调用build方法,返回Environment对象。为什么要用这种写法呢?
我们先来回顾下什么建造者模式:
构建者模式一般用于构建复杂对象时,将复杂对象分割成许多小对象进行分别构建,然后整合在一起形成一个大对象,这样做能很好的规范对象构建的细节过程,这里也是一样的目的,虽然说Environment类的字段较少,但在MyBatis中大量使用构建者模式的基础上,在此处使用构建者模式也无可厚非,而且通过内部类的方式构建,这个Environment对象的创建会在内部类构建方法build()被显式调用时才会在内存中创建,实现了懒加载。这又有点单例模式的意思在内,虽然Mybatis中可创建多个Environment环境,但是在正式运行时,只会存在一个环境,确实是使用内部类实现了懒加载的单例模式。
好了,到这里关于<environments>标签的分析就结束了,后面我们分析下mappers的解析过程。
mybatis源码解析之Configuration加载(四)的更多相关文章
- mybatis源码解析之Configuration加载(五)
概述 前面几篇文章主要看了mybatis配置文件configuation.xml中<setting>,<environments>标签的加载,接下来看一下mapper标签的解析 ...
- mybatis源码解析之Configuration加载(三)
概述 上一篇我们主要分析了下<environments>标签下面,transactionManager的配置,上问最后还有个遗留问题:就是在设置事物管理器的时候有个autocommit的变 ...
- mybatis源码解析之Configuration加载(二)
概述 上一篇我们讲了configuation.xml中几个标签的解析,例如<properties>,<typeAlises>,<settings>等,今天我们来介绍 ...
- mybatis源码解析之Configuration加载(一)
概要 上一篇,我们主要搭建了一个简单的环境,这边我们主要来分析下mybatis是如何来加载它的配置文件Configuration.xml的. 分析 public class App { public ...
- 【MyBatis源码分析】Configuration加载(下篇)
元素设置 继续MyBatis的Configuration加载源码分析: private void parseConfiguration(XNode root) { try { Properties s ...
- 【MyBatis源码分析】Configuration加载(上篇)
config.xml解析为org.w3c.dom.Document 本文首先来简单看一下MyBatis中将config.xml解析为org.w3c.dom.Document的流程,代码为上文的这部分: ...
- webpack4.X源码解析之懒加载
本文针对Webpack懒加载构建和加载的原理,对构建后的源码进行分析. 一.准备工作 首先,init之后创建一个简单的webpack基本的配置,在src目录下创建两个js文件(一个主入口文件和一个非主 ...
- Spring源码解析-配置文件的加载
spring是一个很有名的java开源框架,作为一名javaer还是有必要了解spring的设计原理和机制,beans.core.context作为spring的三个核心组件.而三个组件中最重要的就是 ...
- Mybatis源码学习之资源加载(六)
类加载器简介 Java虚拟机中的类加载器(ClassLoader)负责加载来自文件系统.网络或其他来源的类文件.Java虚拟机中的类加载器默认使用的是双亲委派模式,如图所示,其中有三种默认使用的类加载 ...
随机推荐
- Navicat Premium 12
1.win 客户端软件下载: https://www.navicat.com.cn/download/navicat-premium 2.安装 双击安装--点击下一步 我同意--下一步 选择安装路径- ...
- 读《流畅的python》第一天
1.跟运算符无关的特殊方法了解: 2.跟运算符相关的特殊方法了解: 3.内置的序列类型分类: 容器序列 list.tuple 和 collections.deque 这些序列能存放不同类型的数据. 扁 ...
- 解决js的 Math取正弦值 余弦值不准确的问题
//角度 var vAngle=90: //正弦值 var vSin=Math.round(Math.sin((vAngle * Math.PI/180)) * 1000000) / 1000000 ...
- vector某元素是否存在、查找指定元素 、去重
vector.map 判断某元素是否存在.查找指定元素 [C++]判断元素是否在vector中,对vector去重,两个vector求交集.并集 PS:注意重载
- Docker Swarm Mode 学习笔记 (部署服务)
使用 docker service 命令来管理 Swarm 集群中的服务,该命令只能在管理节点上执行. 新建服务 docker service create --replicas 3 -p 80:80 ...
- thinkphp 操作xml格式
前言:虽然xml的格式看起来跟html差不多,但是最近做项目由于用的是thinkphp5.0的版本,做的过程中还是遇到了一些问题.在这里做一下记录. 首先我们需要定义一个dom对象,我们都知道 php ...
- UP_GetRecordByPage
CREATE PROCEDURE [dbo].[UP_GetRecordByPage] @tblName varchar(255), -- 表名 @fldName varchar(255), -- 主 ...
- 集训队日常训练20181201 C 1003 : 种类数
时间限制(普通/Java):2000MS/6000MS 内存限制:65536KByte总提交: 8 测试通过:5 描述 一共有 n个数,第 i 个数是 xi ,其中xi ...
- windows 根据端口查看进行PID 并杀掉进程
1. 首先用netstat -ano | find “端口号”查出进程号 明明有端口号是17568和18892, 如何确定是17568呢 2. takslist 查询当前的进行 3. 如何杀死进程呢 ...
- Oracle高级查询之over(partition by...)
现有表,数据如下: eg1:查询年龄第二的队员 通常写法: select * from (select a.*, rownum r from (select t.* from l_student_in ...