浩哥解析MyBatis源码(二)——Environment环境
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6625612.html
本应该先开始说Configuration配置类的,但是这个类有点过于复杂,因为MyBatis中的所有配置项全部在这个类中,可谓包罗万象,一开始就讨论如此高大上的东西,貌似有点不合适,认识和学习都应该从小开始,从基础开始,所以我做了这样一个小安排,先挑Configuration中重要的配置项进行了解,心中有了大概印象之后,在进行Configuration的解读,这样就能较为轻松的接受整个其中复杂的配置信息,而不至于不知所措。
首先我们来看看Environment——环境
先说说我们熟悉的内容,当我们单独使用MyBatis框架时(不与Spring框架整合),是需要在Configuration.xml配置文件中进行环境配置的,其代码如下:
- <environments default="development">
- <environment id="development">
- <transactionManager type="JDBC"/>
- <dataSource type="POOLED">
- <property name="driver" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost:3306/mbtest"/>
- <property name="username" value="root"/>
- <property name="password" value="123456"/>
- </dataSource>
- </environment>
- </environments>
从上面的配置内容中可以看出,标签environment代表的就是环境,其有一个属性id,值为“development”(表示开发环境,对应的还会有生产环境),而在其下级节点还需要配置两个内容:transactionManager和DataSource,前者是事务管理器,后者是数据源。“JDBC”表示事务管理器是JDBC类型了,这个标签对应Configuration类创建时在其无参构造器中注册的类型别名,通过这个类型别名注册信息可以找到实际的JDBC事务工厂类:JdbcTransactionFactory(JDBC事务工厂,这个类之后会介绍到,稍安勿躁)。而数据源的类型为“POOLED”类型,同样可以在Configuration类的无参构造器中找到对应的注册信息:PooledDataSourceFactory(表示有连接池的数据源工厂,这个类之后也会介绍)。
而我们要介绍的Environment类就是这个environment标签所代表的环境类,构建Configuration之前,第一步是进行类型别名注册,第二步就是将Environment配置内容从配置文件中读入Environment类中(这一步是在XMLConfigBuilder中完成的),并将其组合到Configuration类中。
Environment类位于org.apache.ibatis.mapping包下,整个类被final修饰,这意味着这个类是个最终类,就如String类一样,是一个不可被更改的类,即其实例是唯一的不能被轻易修改。
下方列出Environment类的源码
- package org.apache.ibatis.mapping;
- import javax.sql.DataSource;
- import org.apache.ibatis.transaction.TransactionFactory;
- /**
- * 环境
- * 决定加载哪种环境(开发环境/生产环境)
- */
- public final class Environment {
- //环境id
- 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;
- }
- //一个静态内部类Builder
- //建造模式
- //用法应该是new Environment.Builder(id).transactionFactory(xx).dataSource(xx).build();
- 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;
- }
- }
通过源码我们可以发现,在Environment类中有三个字段:id、transactionFactory、dataSource,分别对应于配置文件中的三个配置项(id、transactionManager、DataSource),而且这三项均为final类型,表示不可被更改,一次设置终身有效,所以在整个类中也只是使用三参构造器为三项字段赋值,而没有set方法可以进行字段值的更改,只有get方法,可以获取到设置的信息。
Environment类内部有一个静态内部类Builder,这显然是一个构建器类,所以Environgment实例的创建使用了构建者模式(也叫建造者模式)。我们当然可以直接使用外部类的构造器直接进行实例创建,但这并不是MyBatis推荐的(当然其实也不会要求你去手动创建Environgment实例,这里只是打个比方),MyBatis内部进行Environgment实例创建时,就是用其内部构建者进行创建,创建方式和源码中注释里一样:
- new Environment.Builder(id).transactionFactory(xx).dataSource(xx).build();
为什么要使用构建者模式呢?那让我们来回忆一下构建者模式的内容。
构建者模式一般用于构建复杂对象时,将复杂对象分割成许多小对象进行分别构建,然后整合在一起形成一个大对象,这样做能很好的规范对象构建的细节过程,这里也是一样的目的,虽然说Environment类的字段较少,但在MyBatis中大量使用构建者模式的基础上,在此处使用构建者模式也无可厚非,而且通过内部类的方式构建,这个Environment对象的创建会在内部类构建方法build()被显式调用时才会在内存中创建,实现了懒加载。这又有点单例模式的意思在内,虽然Mybatis中可创建多个Environment环境,但是在正式运行时,只会存在一个环境,确实是使用内部类实现了懒加载的单例模式。
这个实例的创建最显然的使用位置就是在XMLConfigBuilder构建器中解析构建Configuration类时在解析了Configuration.xml配置文件中environment标签的内容之后,这个位置用于将读自于配置文件的配置信息配置到了Environment对象中。(这句话有点拗口,不要着急,这个过程在以后介绍XMLConfigBuilder类时会有介绍的)
其实这个类很简单,但它内部包含的TracsactionFactory和DataSource这两个内容又是两大块内容,这一部分容后介绍。
自己理解的还很浅显,希望随着不断的解读源码,能够提升自己的认识,到时候再来这里进行进一步改进。
(未完待续)
浩哥解析MyBatis源码(二)——Environment环境的更多相关文章
- 浩哥解析MyBatis源码(十)——Type类型模块之类型处理器
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6715063.html 1.回顾 之前的两篇分别解析了类型别名注册器和类型处理器注册器,此二 ...
- 浩哥解析MyBatis源码(十二)——binding绑定模块之MapperRegisty
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6758456.html 1.回顾 之前解析了解析模块parsing,其实所谓的解析模块就是为 ...
- 浩哥解析MyBatis源码(八)——Type类型模块之TypeAliasRegistry(类型别名注册器)
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6705769.html 1.回顾 前面几篇讲了数据源模块,这和之前的事务模块都是enviro ...
- 浩哥解析MyBatis源码(七)——DataSource数据源模块之托管数据源
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6675700.html 1 回顾 之前介绍的非池型与池型数据源都是MyBatis自己定义的内 ...
- 浩哥解析MyBatis源码(四)——DataSource数据源模块
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6634880.html 1.回顾 上一文中解读了MyBatis中的事务模块,其实事务操作无非 ...
- 浩哥解析MyBatis源码(五)——DataSource数据源模块之非池型数据源
1 回顾 上一篇中我解说了数据源接口DataSource与数据源工厂接口DataSourceFactory,这二者是MyBatis数据源模块的基础,包括本文中的非池型非池型数据源(UnpooledDa ...
- 浩哥解析MyBatis源码(六)——DataSource数据源模块之池型数据源
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6675674.html 1 回顾 上一文中解读了MyBatis中非池型数据源的源码,非池型也 ...
- 浩哥解析MyBatis源码(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...
- 浩哥解析MyBatis源码(三)——Transaction事务模块
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6634151.html 1.回顾 之前介绍了Environment环境类,这其实是一个单例类 ...
随机推荐
- 【前端】:HTML
前言: 最近开始学前端了,这篇博客主要介绍html的一些主要标签,写完这篇博客,我会用刚学的html做一个简单的登陆界面~~ 一.HTML介绍 HTML(Hyper Text Mark-up Lang ...
- django源码简析——后台程序入口
这一年一直在用云笔记,平时记录一些tips或者问题很方便,所以也就不再用博客进行记录,还是想把最近学习到的一些东西和大家作以分享,也能够对自己做一个总结.工作中主要基于django框架,进行项目的开发 ...
- mac 终端简单指令
pwd 当前工作目录 cd(不加参数) 进root cd(folder) 进入文件夹 cd .. 上级目录 cd ~ 返回root cd - 返回上一个访问的目录 rm 文件名 删除 cat 文件名( ...
- Java 重写hashCode 方法和equals方法
package Container; import java.util.HashSet; import java.util.Iterator; /* Set 元素是无序的(存入和取出的顺序不一定一致) ...
- webpack入门与解析(一)
每次学新东西总感觉自己是不是变笨了,看了几个博客,试着试着就跑不下去,无奈只有去看官方文档. webpack是基于node的.先安装最新的node. 1.初始化 安装node后,新建一个目录,比如ht ...
- windows下部署免费ssl证书(letsencrypt)
随着网络的发展,网络安全也越来越重要,对于网站来说,从Http升级到https也是我们要做的首要事情.要实现https,首先我们需要申请一张SSL证书,这篇文章我主要介绍下边这几个方面: 1. SSL ...
- Javascript面对对象. 第三篇
3.字面量 为了让属性和方法很好的体现封装的效果,并且减少不必要的输入原型的创建可以使用字面量. function Box(){} //使用字面量的方法创建原型对象,这里的{}就是对象,是Object ...
- Cassandra issue - "The clustering keys ordering is wrong for @EmbeddedId"
在Java连接Cassandra的情况下, 当使用组合主键时, 默认第一个是Partition Key, 后续的均为Clustering Key. 如果有多个Clustering Key, 在Java ...
- matlab分割背景与物体
[name,path]=uigetfile('*.jpg;*.png;*.bmp','选择一张图片');f=imread([path name]);count = 0; T = mean2(f); d ...
- 自行搭建私有云ownCloud,启用SSL,其他配置
ownCloud简介 ownCloud(官网)是一款开源的私有云框架,可以通过它实现个人网盘的功能,如果拥有一个性能不错的VPS,那么就可以摆脱奇慢无比的百度云等网盘啦!我花了大约一天的时间总算搭好了 ...