Mybatis源码分析_日志模块 (1)

news/2024/10/30 13:34:59/

不得不承认,学习MyBatis的时间成本要比学习Spring低很多,Mybatis是我所了解过的代码量最小、整体架构最简单,但是又是最具有学习价值的一个框架。如果,你想快速的阅读一个框架的源码,并且掌握这个框架的精髓,那么Mybatis一定是你的首选。

在开始我们的源码阅读之前,我们先来学习一个设计模式:

适配器模式

 大话数据结构是这样解释的:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能在一起工作的哪些类可以在一起工作,这就是适配器模式。

什么意思呢?

简单解释一下,客户方希望调用一个类的 A ,B方法, 但是这个类是第三方框架的,或者说这个类早就写好了,不可能因为你的想法而改变。而这个类有C, D 方法。那么怎么办呢?这时候我们可以定义一个类,类中定义A,B方法, 而A方法就是简单的调用C方法,B方法就是简单的调用D方法,这就是适配器模式的雏形。

当需要定义很多个这样的类的时候,我们就可以定义一个接口,而这些需要定义的类都来实现这个接口,这就是适配器模式了。

代码说明:

被适配对象,也就是说这个类早就存在了,不允许更改。

package com.sjmx.adapter;//已存在的、具有特殊功能、但不符合我们既有的标准接口的类
public class Adaptee1 {public void specificRequest() {System.out.println("被适配类具有 特殊功能1...");}}
package com.sjmx.adapter;//已存在的、具有特殊功能、但不符合我们既有的标准接口的类
public class Adaptee2 {public void verifyRequest() {System.out.println("被适配类具有 特殊功能2...");}}

但是客户方希望调用这两个类,并且这两个类的方法名都必须是 aRequest(), 怎么办呢?这时候就需要适配器模式发光发热了。

首先定义一个接口:

package com.sjmx.adapter;//目标接口,或称为标准接口
public interface Target {public void aRequest();
}

定义两个实现类Adapter1 和Adapter2,分别对应Adaptee1 和 Adaptee2.

package com.sjmx.adapter;//适配器类,直接关联被适配类,同时实现标准接口
public class Adapter1 implements Target {// 直接关联被适配类private Adaptee1 adaptee;// 可以通过构造函数传入具体需要适配的被适配类对象public Adapter1 () {this.adaptee = new Adaptee1();}public void aRequest() {// 这里是使用委托的方式完成特殊功能this.adaptee.specificRequest();}}
package com.sjmx.adapter;//适配器类,直接关联被适配类,同时实现标准接口
public class Adapter2 implements Target {// 直接关联被适配类private Adaptee2 adaptee;// 可以通过构造函数传入具体需要适配的被适配类对象public Adapter2 () {this.adaptee = new Adaptee2();}public void aRequest() {// 这里是使用委托的方式完成特殊功能this.adaptee.verifyRequest();}}

模拟客户方调用:

package com.sjmx.adapter;public class Client {public static void main(String[] args) {//调用Adaptee1Target adapter = new Adapter1();adapter.arequest();//调用Adaptee2Target adapter = new Adapter2();adapter.arequest();}
}

客户方只知道有这么个接口,并且还需要知道这个接口对应的实现类,然后根据自己的需要自己去new出来实现类并且调用符合规范的方法就ok了,这就是完整的适配器模式。

这个设计模式很大的解决了客户的新需求与老系统的兼容性问题,但是它也是有缺点的。比如,我们的客户方每次调用都需要适配器对应的类是谁,功能是干嘛的,增加了代码的耦合度。而且,一旦哪天某一个具体的Adapter废弃掉了,或者类改名字了,但是这个类在客户方大量使用,我们是不是要到客户方代码中,把所有调用这个类的地方都得改一遍?

此时,我们就遇到的困难是如何去实例化这个Adapter,这就引出了简单工厂实际模式

简单工厂模式

简单工厂设计模式,说白了就是负责实例化对象的。如果一个接口有几个实现类,我们该调用具体的哪一个实现类,这就是简单工厂负责的事情。

 简单工厂、工厂、抽象工厂,在底层框架中都会被大量的使用到的。由于简单工厂实在太简单了,这里就不多说了,不了解的可以看我的 《大话设计模式》——读后感 (1)代码无错就是优?——简单工厂模式_chen_yao_kerr的博客-CSDN博客

Mybatis的日志模块巧妙整合 适配器设计模式 和 简单工厂设计模式

1.首先定义一个Log接口,这个接口规定好了具体的日志级别

2. 针对不同的日志框架,都提供一个适配器类Adapter,并且这些适配器都实现了这个接口

3. 利用简单工厂,把需要被代理对象按照优先级准备好。也就是把日志框架的Adapter准备好

4. 日志框架,肯定是按照优先级使用的。因此,mybatis的设计是如果已经找到了优先级中符合的日志框架Adapter,那么后面的框架都会轮空的。也就是说找到了合适的日志框架,那后面的框架就不要再new出来构造器Constructor对象了

6. 最为精妙的是,这个日志的简单工厂 LogFactory 还提供了一个泛型的getLog方法。而这个方法传递了业务类的Class文件,根据适配器Adapter的构造器对象和业务对象的Class文件,去实例化当前日志框架的具体Adater对象。神来之笔。

 

 下面随处找一个Mybatis的文件,验证一下我们的观点:

这样一来,即使Mybatis把整个日志框架换掉,我们调用方的代码也不需要做任何的修改。因为Log接口是我们自己定义的,每个Adapter都有对应的Adaptee。而更换日志框架,LogFactory有完整的逻辑帮我们处理,并且提供了统一的调用方法 getLog(Class<?> clazz),  客户调用方完全就不需要知道适配器(Adapter)是谁,被适配的对象(Adaptee)是谁,我也不管你改没改,我只要知道统一的Log接口,还有一个LogFactory对象就ok,完全达到了解耦的效果,简直就是神来之笔啊。

以前,我们的业务代码使用哪个日志框架,都需要引入这个框架的包路径,一旦更改日志框架,所有的地方都得改,改动数量可不会少,动不动还容易出错:

 而现在,如果我们自己定义的Log接口,我管你日志框架改没改呢,我管你日志框架是每天换一个,还是每小时换一个呢,我只关注我自己的Log接口及其实现类,他们都写好了,以不变应万变,堪称完美。mybatis就是这样做的:

 

这个设计思想,此处的代码,太值得借鉴!


http://www.ppmy.cn/news/503649.html

相关文章

python修改桌面壁纸_轻松有趣的Python小案例,让电脑自动更换壁纸

周末好&#xff01;难得放假&#xff0c;今天的你是不是一觉睡到大中午了&#xff1f;不要有愧疚感&#xff0c;现在的年轻人压力实在太大&#xff0c;好好睡上一觉已经是一件很奢侈的事情了&#xff0c;就给自己好好放个假吧&#xff01; 在这难得的休闲时光&#xff0c;我们…

什么是版本控制系统?怎么学习? - 易智编译EaseEditing

版本控制系统&#xff08;Version Control System&#xff0c;简称VCS&#xff09;是一种用于管理和跟踪文件版本的工具或系统。它可以追踪文件的变更历史&#xff0c;记录每个版本的修改内容&#xff0c;以及支持多人协作开发。 学习版本控制系统可以帮助你更好地管理和控制你…

每一次Http请求,Java线程是如何处理的?

每一次Http请求&#xff0c;Java线程是如何处理的&#xff1f; 文章目录 每一次Http请求&#xff0c;Java线程是如何处理的&#xff1f;前言一、Http请求处理二、两种服务器模型及处理方式1、两种服务&#xff1a;2.更好的处理方式 总结 前言 当我们写好一个项目时&#xff0c…

在 Navicat Premium 中管理 MySQL 用户 | 第 2 部分:创建新用户

第 2 部分&#xff1a;创建新用户 第 2 部分&#xff1a;创建新用户 第 1 部分 中&#xff0c;我们学习了如何使用 Navicat Premium 用户管理工具保护 MySQL 的 root 帐号。本篇文章将集中介绍如何设置新用户的帐号详细信息、帐号限制和 SSL 设置。如果你想边学边用&#xff1…

typeScript(枚举篇)

枚举 使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。 数字枚举 首先我们看看数字枚举&#xff0c;如果你使用过其它编程语言应该会很熟悉。 enum Direction {Up 1,Down,Left,Righ…

字体取消加粗

默认字体太粗&#xff0c;不加粗 font-weight: 400;

CSS字体的加粗

font-weight normal:正常字体 bold&#xff1a;加粗 还可以利用100-900之间的整百数 400&#xff1a;normal 700&#xff1a;bold

Latex字体加粗不了

最近用latex写英文文章&#xff0c;latex字体加粗斜体一直无效&#xff0c;\textbf{}和\bfSeries{}没用&#xff0c;标题表格加黑也显示不出来&#xff0c;无奈之下用公式环境加粗\bm{}实现的&#xff0c;但也有很多不便之处&#xff0c;刚刚才发现解决的办法&#xff0c;就是把…