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

news2024/11/16 11:49:57

不得不承认,学习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) {
        
        //调用Adaptee1
        Target adapter = new Adapter1();
        adapter.arequest();

        //调用Adaptee2
        Target 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.coloradmin.cn/o/671067.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅析GeoServer CVE-2023-25157 SQL注入

简介 GeoServer是一个开源的地图服务器&#xff0c;它是遵循OpenGIS Web服务器规范的J2EE实现&#xff0c;通过它可以方便的将地图数据发布为地图服务&#xff0c;实现地理空间数据在用户之间的共享。 影响版本 geoserver<2.18.7 2.19.0<geoserver<2.19.7 2.20.0…

国内外八大敏捷开发工具盘点

1、Leangoo领歌&#xff1b;官网&#xff1a;Leangoo领歌 - 高效企业必备的敏捷工具,Scrum工具,SAFe敏捷工具,敏捷项目管理,敏捷研发工具 2、VersionOne&#xff1b;官网&#xff1a;https://www.collab.net/products/versiononehttps://www.collab.net/products/versionone …

Python高级系列教程:Python高级语法与正则表达式

学习目标 1、能够掌握with语句的使用 2、能够知道生成器的两种创建方式 3、能够知道深拷贝和浅拷贝的区别 4、能够掌握Python中的正则表达式编写 一、Python高级语法 1、with语句和上下文管理器 ☆ with语句 Python提供了 with 语句的写法&#xff0c;既简单又安全。文件操…

Vue-scoped(局部)样式

scoped(局部)样式 scoped是在脚手架有一个编写样式的小技巧 作用&#xff1a;让样式在局部生效&#xff0c;防止冲突 1 编写案例 现在有两个组件&#xff0c;一个student,一个school&#xff0c;现在想给组件写点样式 这里只给个背景色 没问题&#xff0c;样式生效 2 样式冲…

docker canal 安装

(373条消息) 使用 Docker 部署 canal 服务_canal docker部署_qq2276031的博客-CSDN博客https://blog.csdn.net/qq2276031/article/details/120234122 docker canal github 网址 Canal Admin Docker alibaba/canal Wiki (github.com)https://github.com/alibaba/canal/wiki/Ca…

璞华产业园区租赁运营平台,助力空间资产管理数字化转型!

{ 产业园区租赁运营平台 } 直面行业痛点 专注技术创新 点击输入图片描述&#xff08;最多30字&#xff09; 产业园区作为产业转型升级的重要载体&#xff0c;产业园区租赁运营也正迎来新的发展机遇。璞华一直关注为客户智能化转型过程中提供的服务&#xff0c;能否将技术方案…

【自监督论文阅读 3】DINOv1

文章目录 一、摘要二、引言三、相关工作3.1 自监督学习3.2 自训练与知识蒸馏 四、方法4.1 SSL with Knowledge Distillation4.2 教师网络4.3 网络架构4.4 避免坍塌 五、实验与评估六、消融实验6.1 不同组合的重要性6.2 教师网络选择的影响6.3 避免坍塌6.4 在小batch上训练 七、…

elk搭建

1、前言 ELK 是一个开源的日志管理解决方案&#xff0c;主要是为了统一收集生产的日志&#xff0c;方便日志的查询&#xff0c;传统的日志都是保存在每个机器上&#xff0c;当要查询的时候&#xff0c;需要到每一台机器上去查询日志&#xff0c;非常麻烦&#xff0c;而elk则使…

阿里巴巴 Java 开发手册部分整理

阿里巴巴 Java 开发手册 一、编程规约(一) 命名风格(二) 常量定义(三) 代码格式(四) OOP 规约(五) 集合处理(六) 并发处理(七) 控制语句(八) 注释规约(九) 其它 二、异常日志(一) 异常处理(二) 日志规约 三、单元测试四、安全规约五、MySQL 数据库(一) 建表规约(二) 索引规约(三…

Java 操作pdf工具类

1、获取pdf页数 添加maven依赖&#xff1a; <!-- java获取Pdf文件页码 --><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>1.8.11</version></dependency>代码实现&#x…

Goby 漏洞发布|电信网关配置管理系统后台 /manager/teletext/material/upload.php 文件上传漏洞

漏洞名称&#xff1a;电信网关配置管理系统后台 /manager/teletext/material/upload.php 文件上传漏洞 English Name&#xff1a;Telecom system /manager/teletext/material/upload.php fileupload vulnerability CVSS core: 9.8 影响资产数&#xff1a;856 漏洞描述&…

不过时的经典层架构

在《设计服务要考虑的7个维度》中讲到设计一定要把不稳定的部分做封装。今天咱们就从这个角度重新审视一下经典的四层架构。 上面是一个经典层架构的示意图。这个架构大多数的公司和项目都在直接用&#xff0c;或者用其变体。 比如&#xff0c;某大厂上层Client客户端可能是电商…

安卓蓝牙GATT协议介绍

前言 现在低功耗蓝牙&#xff08;BLE&#xff09;连接都是建立在 GATT (Generic Attribute Profile) 协议之上。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范&#xff0c;这些很短的数据段被称为属性&#xff08;Attribute&#xff09;。 GAP 详细介绍 GAT…

GBASE金融信创优秀解决方案鉴赏 · 核心业务系统数据库解决方案

为此&#xff0c;实验室特别开设金融信创优秀解决方案专栏&#xff0c;集中展示优秀成果。现在&#xff0c;让我们一起来领略下GBASE的优秀解决方案吧~可点击阅读原文 →《金融信创优秀解决方案--核心业务系统数据库解决方案》。 核心业务系统数据库解决方案 方案简介 随着技…

Android Qcom USB Driver学习(十三)

该系列文章总目录链接与各部分简介&#xff1a; Android Qcom USB Driver学习(零) Android Qcom USB Driver学习(八) Android Qcom USB Driver学习(九) UCSI USB Type-C Connector System Software Interface Specification DPM Device Policy Manager deals with the USB P…

智安网络|驾驭数字化转型时代:加速业务转型的战略

随着科技的飞速发展和数字化时代的到来&#xff0c;企业面临着前所未有的机遇和挑战。数字化正在改变着商业的方方面面&#xff0c;而那些能够及时适应和把握这些变化的企业将脱颖而出。因此&#xff0c;加速企业转型成为了当务之急。 一、为什么需要加速企业转型 1.全球市场竞…

D. Pairs of Segments(最大不相交区间数量)

Problem - D - Codeforces 给定一个由n个线段组成的数组[[l1,r1],[l2,r2],…,[ln,rn]]&#xff0c;其中每个线段用左右端点表示。如果存在至少一个x满足l1≤x≤r1且l2≤x≤r2&#xff0c;则称线段[l1,r1]和[l2,r2]相交。 如果k为偶数&#xff0c;并且可以将该数组的元素分成k/…

VTK裁剪【3】-vtkClipPolyDatavtkPolyPlane问题

前言&#xff1a;本博文主要记录vtkClipPolyData中采用vtkPolyPlane作为裁剪工具时的出现的问题&#xff0c;供各位小伙伴进行参考&#xff0c;避免踩坑&#xff01; 目录 vtkPolyPlane介绍及作用 vtkClipPolyData原理 实现流程&#xff1a; 问题所在&#xff1a; 需求&…

css绘制网格背景

文章目录 前言效果图说明 前言 本篇文章主要简单扼要的去实现css网格背景&#xff0c;并进一步探求其应用原理 效果图 css代码 body::before, body::after {position: fixed;top: 0;left: 0;right: 0;bottom: 0;content: ;background-repeat: repeat;pointer-events: none;o…

企业特权密码管理

随着企业中特权帐户的激增&#xff0c;必须保护的密码数量也大幅增长。跟踪所有这些密码是一项艰巨的任务&#xff0c;为避免敏感密码管理不善&#xff0c;管理员需要在集中式存储库下清点属于所有部门的密码&#xff0c;并管理对它们的直接控制。 部署PMP的好处 PMP是一个安…