【面试精讲】MyBatis设计模式及源码分析,MyBatis设计模式实现原理

news2024/11/26 14:43:07

【面试精讲】MyBatis设计模式及源码分析,MyBatis设计模式实现原理

目录

本文导读

一、MyBatis中运用的设计模式详解

1. 工厂模式(Factory Pattern)

2. 单例模式(Singleton Pattern)

3. 建造者模式(Builder Pattern)

4. 代理模式(Proxy Pattern)

5. 模板方法模式(Template Method Pattern)

6. 策略模式(Strategy Pattern)

7. 观察者模式(Observer Pattern)

二、MyBatis设计模式的源码实现原理

工厂模式的应用 - SqlSessionFactory

单例模式的应用 - SqlSessionFactory

代理模式的应用 - Mapper动态代理

建造者模式(Builder Pattern)

策略模式 - Strategy Pattern

观察者模式 - Observer Pattern

三、MyBatis源码解析

工厂模式 - SqlSessionFactoryBuilder

单例模式 - SqlSessionFactory

代理模式 - MapperProxyFactory

总结

 博主v:XiaoMing_Java


本文导读

MyBatis是一个流行的持久层框架,它极大地简化了数据库操作,提升了开发效率。在其底层实现中,MyBatis广泛采用了各种设计模式,这些设计模式不仅增加了框架的灵活性和可维护性,也为开发人员提供了丰富的使用场景和扩展能力。本文将深入探讨MyBatis所应用的主要设计模式及其在框架中的具体应用。

一、MyBatis中运用的设计模式详解

1. 工厂模式(Factory Pattern)

工厂模式是一种创建型模式,它提供了一种创建对象的最佳方式。在MyBatis中,SqlSessionFactoryBuilderSqlSessionFactory等关键组件的创建过程就运用到了工厂模式。尤其是SqlSessionFactory的创建,它是通过SqlSessionFactoryBuilder读取MyBatis配置文件并构建出SqlSessionFactory实例。这样做可以隔离复杂的初始化过程,使用户只需关注最终产出,而无需了解创建实例的复杂过程。

2. 单例模式(Singleton Pattern)

单例模式确保一个类只有一个实例,并提供一个全局访问点。在MyBatis中,SqlSessionFactory的设计就是单例模式的经典应用。一旦通过SqlSessionFactoryBuilder创建了SqlSessionFactory实例后,该实例就会在应用程序中被复用,避免了重复创建实例带来的资源浪费。

3. 建造者模式(Builder Pattern)

建造者模式旨在将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。MyBatis中的XMLConfigBuilderXMLMapperBuilder等类的设计采用了建造者模式。这些Builder类负责解析MyBatis的配置文件和映射文件,逐步构建出配置信息和映射信息。通过建造者模式,MyBatis将复杂的解析过程分解成一系列的步骤,使得代码更加清晰和易于维护。

4. 代理模式(Proxy Pattern)

代理模式为其他对象提供一个代理以控制对这个对象的访问。MyBatis中对Mapper接口的实现就是基于JDK动态代理机制。当调用Mapper接口的方法时,实际上是由MyBatis生成的代理类去执行。这种方式允许MyBatis在执行Mapper方法前后插入自定义逻辑,如开启事务、处理缓存等,从而大幅提升了灵活性和可扩展性。

5. 模板方法模式(Template Method Pattern)

模板方法模式定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。MyBatis的BaseExecutor类就是一个模板方法模式的例证。它定义了数据库操作的基本流程,如查询、更新、提交事务等,而具体的执行逻辑则留给其子类(比如SimpleExecutorBatchExecutor等)去实现。这样做的好处是复用了代码,同时又保留了灵活性。

6. 策略模式(Strategy Pattern)

策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以相互替换。MyBatis中的缓存策略、加载策略等正是策略模式的应用。例如,MyBatis允许用户配置不同的缓存实现(如EHCache、OSCache等),并在运行时根据配置动态选择。这种模式使得MyBatis具有很高的灵活性和扩展性。

7. 观察者模式(Observer Pattern)

观察者模式定义了一种依赖关系,当一个对象状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在MyBatis中,Configuration对象就是一个观察者,它会监听映射文件的解析事件,并在解析完成后更新自己的状态。通过观察者模式,MyBatis能够动态响应配置信息的变化,增强了框架的动态性和灵活性。

以上便是MyBatis中常见的几种设计模式及其应用。这些设计模式的运用大大提升了MyBatis的内聚性、可扩展性和灵活性,使得MyBatis成为了Java领域广泛使用的ORM框架之一。

二、MyBatis设计模式的源码实现原理

在第一部分中,我们讨论了MyBatis使用的一些关键设计模式及其作用。现在,我们将深入探索这些设计模式在MyBatis源码中的具体实现原理。

工厂模式的应用 - SqlSessionFactory

实现原理:

SqlSessionFactory的创建是通过SqlSessionFactoryBuilder完成的。这个过程遵循了典型的工厂模式设计,SqlSessionFactoryBuilder充当工厂的角色,负责生产SqlSessionFactory对象。

public SqlSessionFactory build(Reader reader) {
    // 使用XMLConfigBuilder解析配置文件
    XMLConfigBuilder parser = new XMLConfigBuilder(reader, null, null);
    return build(parser.parse());
}

在上述代码中,build方法首先通过XMLConfigBuilder解析给定的配置文件,然后根据解析结果构建出一个SqlSessionFactory实例。这个过程封装了对象的创建逻辑,使得客户端代码无需直接与对象的创建细节打交道。

单例模式的应用 - SqlSessionFactory

实现原理:

在MyBatis中,通常我们会将SqlSessionFactory作为单例存在,以保证全局只有一个数据库连接池,从而节省资源。、

public class MyBatisUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }
}

在这段代码中,利用静态初始化块加载配置并创建SqlSessionFactory,确保了其单例性。此外,通过提供一个静态方法getSqlSessionFactory来全局访问该实例,进一步体现了单例模式的特点。

代理模式的应用 - Mapper动态代理

实现原理:

MyBatis中对Mapper接口的实现是基于JDK动态代理的。当调用Mapper接口的方法时,实际上是委托给了由MyBatis动态生成的代理类。

public class MapperProxy<T> implements InvocationHandler {

    private final SqlSession sqlSession;
    private final Class<T> mapperInterface;

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 方法调用的处理逻辑
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }
        // 执行SQL操作
        return sqlSession.selectList(mapperInterface.getCanonicalName() + "." + method.getName());
    }
}

建造者模式(Builder Pattern)

MyBatis在处理配置文件时,使用了建造者模式。XMLConfigBuilderXMLMapperBuilder是两个具体的例子,它们负责解析MyBatis的配置文件和映射文件。

实现原理:这段代码展示了BaseExecutor中的query方法,这是一个模板方法,它定义了执行查询的基本流程,并将具体的查询逻辑委托给doQuery方法。子类需要根据不同的需求实现doQuery方法,比如SimpleExecutorReuseExecutor等都有各自的实现,这正是模板方法模式的典型应用。

public class XMLConfigBuilder extends BaseBuilder {
    private boolean parsed;
    private final XPathParser parser;

    public XMLConfigBuilder(InputStream inputStream) {
        this(new XPathParser(inputStream, true, null));
    }

    public Configuration parse() {
        if (parsed) {
            throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        }
        parsed = true;
        // 省略解析过程...
        return configuration;
    }
}
策略模式 - Strategy Pattern

MyBatis的缓存策略使用了策略模式。MyBatis允许用户选择或自定义缓存实现,这是通过将缓存行为抽象成接口,并允许动态设置具体实现来实现的。

实现原理:Cache接口定义了缓存的行为,而PerpetualCache提供了Cache接口的一个基础实现。MyBatis还支持更多缓存实现,如OSCache、Ehcache等,开发人员可以根据需要选择或自定义缓存策略,这体现了策略模式的灵活性。

public interface Cache {
    void putObject(Object key, Object value);
    Object getObject(Object key);
    // 更多方法...
}

public class PerpetualCache implements Cache {
    private Map<Object, Object> cache = new HashMap<>();

    @Override
    public void putObject(Object key, Object value) {
        cache.put(key, value);
    }

    @Override
    public Object getObject(Object key) {
        return cache.get(key);
    }
    // 实现其他方法...
}
观察者模式 - Observer Pattern

MyBatis利用观察者模式来实现插件功能。插件可以在MyBatis操作数据库的关键节点被插入,比如执行查询之前。这种机制使得用户能够在不修改MyBatis核心代码的情况下,扩展其功能。

实现原理:Interceptor接口定义了插件需要实现的intercept方法。SomePlugin是一个具体的插件实现,它可以在方法调用前后执行额外的逻辑。这种方式使得MyBatis能够在运行时灵活地扩展功能,体现了观察者模式的特点。

public interface Interceptor {
    Object intercept(Invocation invocation) throws Throwable;
    // 更多方法...
}

public class SomePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 在执行前后添加额外的操作
        Object returnObject = invocation.proceed();
        // 在执行后处理
        return returnObject;
    }
}

三、MyBatis源码解析

深入探讨MyBatis的源码对于理解其设计模式的应用至关重要。由于篇幅限制,我们将通过几个关键组件的源码片段来揭示MyBatis是如何实现上文提到的设计模式的。请注意,下面的代码是简化版本,旨在帮助理解其核心原理。

工厂模式 - SqlSessionFactoryBuilder

MyBatis通过SqlSessionFactoryBuilder创建SqlSessionFactory的过程是工厂模式的一个典型应用。

public class SqlSessionFactoryBuilder {
    public SqlSessionFactory build(Reader reader) {
        // 解析配置文件,构建Configuration对象
        XMLConfigBuilder parser = new XMLConfigBuilder(reader);
        Configuration config = parser.parse();

        // 返回SqlSessionFactory实例
        return new DefaultSqlSessionFactory(config);
    }
}
单例模式 - SqlSessionFactory

虽然MyBatis不直接提供SqlSessionFactory的单例实现,但在实际应用中,开发者通常会将其实现为单例模式,以下是一个简单的示例:

public class MyBatisUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }
}
代理模式 - MapperProxyFactory

MyBatis使用JDK动态代理为Mapper接口生成代理对象,以便拦截接口方法的调用。

public class MapperProxy<T> implements InvocationHandler {
    private final SqlSession sqlSession;
    private final Class<T> mapperInterface;

    public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 省略具体实现
        return sqlSession.selectList(mapperInterface.getCanonicalName() + "." + method.getName());
    }
}

public class MapperProxyFactory<T> {
    private final Class<T> mapperInterface;

    public MapperProxyFactory(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }

    public T newInstance(SqlSession sqlSession) {
        MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface);
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
    }
}

总结

每个设计模式的实现都体现了MyBatis设计的巧妙和优雅,通过这些模式的应用,MyBatis成功地将框架的灵活性、可扩展性和维护性提升到了一个新的高度。希望通过这三部分的解析,你能对MyBatis的设计和实现有一个更加深入的理解。

 如果本文对你有帮助 欢迎 关注 、点赞 、收藏 、评论, 博主才有动力持续创作!!!

 博主v:XiaoMing_Java

  📫作者简介:嗨,大家好,我是  小明 ,互联网大厂后端研发专家,2022博客之星TOP3 / 博客专家 / CSDN后端内容合伙人、InfoQ(极客时间)签约作者、阿里云签约博主、全网 6 万粉丝博主。


🍅 文末获取联系 🍅  👇🏻 精彩专栏推荐订阅收藏 👇🏻

专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

🔥Redis从入门到精通与实战🔥

Redis从入门到精通与实战

围绕原理源码讲解Redis面试知识点与实战

🔥MySQL从入门到精通🔥

MySQL从入门到精通

全面讲解MySQL知识与企业级MySQL实战

🔥计算机底层原理🔥

深入理解计算机系统CSAPP

以深入理解计算机系统为基石,构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

🔥数据结构与企业题库精讲🔥

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

🔥互联网架构分析与实战🔥

企业系统架构分析实践与落地

行业最前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

互联网金融公司的防资损方法论、代码与实践

🔥Java全栈白宝书🔥

精通Java8与函数式编程

本专栏以实战为基础,逐步深入Java8以及未来的编程模式

深入理解JVM

详细介绍内存区域、字节码、方法底层,类加载和GC等知识

深入理解高并发编程

深入Liunx内核、汇编、C++全方位理解并发编程

Spring源码分析

Spring核心七IOC/AOP等源码分析

MyBatis源码分析

MyBatis核心源码分析

Java核心技术

只讲Java核心技术

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1582515.html

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

相关文章

GEE图表案例——不同区域各地类面积直方图分布图表(矢量面积叠加直方图图)

简介 在GEE中对不同区域面积统计的直方图绘制具体流程如下: 数据准备: 首先,需要准备用于面积统计的地理数据,可以是矢量数据,如行政边界、土地使用类型等。也可以是栅格数据,如分类结果、土地覆盖数据等。 区域划分: 根据需要统计的区域,将数据进行区域划分。可以使用…

电商技术揭秘七:搜索引擎中的SEO关键词策略与内容优化技术

文章目录 引言一、关键词策略1.1 关键词研究与选择1. 确定目标受众2. 使用关键词研究工具3. 分析搜索量和竞争程度4. 考虑长尾关键词5. 关键词的商业意图6. 创建关键词列表7. 持续监控和调整 1.2 关键词布局与密度1. 关键词自然分布2. 标题标签的使用3. 首次段落的重要性4. 关键…

00后应届毕业生面试要一万,面试官:不好意思,我们给不起

前几天&#xff0c;小编收到了即将毕业的表弟发来的私信&#xff0c;说他刚刚面试一家单位被刷了。表弟专业学的不错&#xff0c;人也十分聪明&#xff0c;家里人们都对这个面试结果感到吃惊&#xff0c;一问才知&#xff0c;被刷的理由很简单&#xff1a;开了10K的工资&#x…

FPGA笔试面试题目记录

1 logic utilization 题目&#xff1a;Rank the following operations from lowest utilization to highest. Assume that all variables are 32-bit integers,that the operations are implemented using LUTs ony and that the synthesiser will produce an optimal digital…

基于springboot实现医院管理系统项目【项目源码+论文说明】

基于springboot实现医院管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计算机管理医院管理系统的方案。文章介绍了医院管理系…

cesium 动态墙效果 电子围栏效果

一、扩展材质 /*** 动态墙材质* param {*} options* param {String} options.color 颜色* param {Number} options.duration 持续时间 毫秒* param {String} options.trailImage 贴图地址*/function DynamicWallMaterialProperty(options) {this._definitionChanged new Cesi…

软件设计—接口安全设计规范

1.token授权机制 2.https传输加密 3.接口调用防滥用 4.日志审计里监控 5.开发测试环境隔离&#xff0c;脱敏处理 6.数据库运维监控审计 软件项目相关全套精华资料包获取方式①&#xff1a;点我获取 获取方式②&#xff1a;本文末个人名片直接获取。

synchronized锁机制升级过程——面试题

1. 无锁状态 对象在没有被任何线程锁定时处于无锁状态。此时对象头中的锁标志位通常表示为无锁&#xff08;例如&#xff0c;标记字段的特定位组合表示无锁或偏向锁状态&#xff09;。 2. 偏向锁&#xff08;Biased Locking&#xff09; 初次获取&#xff1a;当线程首次获得…

SpringMVC--核心概念 / @RequestMapping注解

目录 1. 准备工作 1.1. 创建SpringMVC-demo02 子模块 1.2. 添加相关依赖 1.3. 设置 Maven 打包方式 1.4. 配置 web.xml 文件 1.4.1. 创建 web.xml 文件 1.4.2. 默认配置方式 1.4.3. 扩展配置方式 1.4.4. 注意点 1.5. 配置 Spring 文件 1.5.1. Thymeleaf视图解析器 …

知识图谱的最新进展与未来趋势

知识图谱的最新进展与未来趋势 一、引言 在过去的几年中&#xff0c;知识图谱已经从一个前沿的研究概念发展成为现代信息技术不可或缺的一部分。作为结构化知识的存储和表示形式&#xff0c;知识图谱通过组织信息和数据提供了深刻的洞见&#xff0c;它已被广泛应用于搜索引擎优…

HarmonyOS4-学习入门知识总结

简单的组件学习&#xff1a; /*** weip 自定义控件* 自定义构建函数也是需要充电的地方&#xff0c;分全局和局部的* 全局&#xff1a;需要添加function关键字 局部&#xff1a;不加function关键字* Styles function 自定义公共样式 分全局和局部* Extends(Text) 继承模式 只…

springboot 创建子模块时 pom 配置

创建子模块 2. 修改父模块 pom 文件 添加如下内容 <packaging>pom</packaging><modules><module>mybatisconf</module></modules>3. 修改子模块 pom 文件 <parent><groupId>com.vazquez</groupId><artifactId>bo…

wangEditor 测试环境对,但是生产环境无法显示

package.json 文件版本 "wangeditor": "4.3.0"开发环境 new Editor(#${this.id});出来的数据 正式环境 new Editor(#${this.id});出来的数据 原因&#xff1a; vue.config 文件 打包策略的时候 const assetsCDN {css: [https://lf6-cdn-tos.bytecd…

python中报错“ModuleNotFoundError: No module named ‘openpyxl‘”

python中报错“ModuleNotFoundError: No module named ‘openpyxl’” 问题描述 运行python代码时&#xff0c;报错“ModuleNotFoundError: No module named ‘openpyxl’” 解决方案&#xff1a; 可能是没有安装openpyxl&#xff0c; # 安装命令 pip install openpyxl #…

如何恢复未保存或删除/丢失的Word文件?

关闭 Word 应用程序而不保存文档&#xff1f;误删Word文档&#xff1f;许多用户会在不同的情况下丢失Word文档。如果不幸遇到此类问题&#xff0c;如何恢复已删除或未保存的 Word 文档&#xff1f;有一些方法可以恢复未保存/删除的文档。此外&#xff0c;您还可以使用Word文件恢…

【USB 】Jack (Female) Type A Connectors 2 Port Mounting Peg

1. NO BACK SHIELD&#xff0c;NO ARMS&#xff0c;FRONT GROUNDING ARMS 2. BACK SHIELD&#xff0c;NO FRONT GROUNDING ARMS 3. NO BACK SHIELD&#xff0c;FRONT GROUNDING ARMS 4. BACK SHIELD&#xff0c;FRONT GROUNDING ARMS

金铲铲单机版含教程,仅支持S1\S6\S11赛季

金铲铲单机版&#xff0c;官方的单机版&#xff0c;支持S3/S6/S11赛季&#xff0c; 我自己玩了两把&#xff0c;可以加金币/加血/设置GM权限等&#xff0c; 我猜测是开发者测试版本&#xff0c; 金铲铲单机版含教程&#xff0c;仅支持S1\S6\S11赛季 网盘自动获取 链接&#xff…

基于springboot+vue实现新闻推荐系统项目【项目源码+论文说明】

基于springboot实现新闻推荐系统演示 摘要 随着信息互联网购物的飞速发展&#xff0c;国内放开了自媒体的政策&#xff0c;一般企业都开始开发属于自己内容分发平台的网站。本文介绍了新闻推荐系统的开发全过程。通过分析企业对于新闻推荐系统的需求&#xff0c;创建了一个计算…

MySQL 优化总结

目标知识 MySQL执行流程图 MySQL 优化成本路线图 优化成本&#xff1a;硬件>系统配置>数据库表结构>SQL及索引。优化效果&#xff1a;硬件<系统配置<数据库表结构<SQL及索引。 MySQL 五大优化原则 减少数据返回&#xff1a;设置合理字段数据类型、启用压缩…

深入理解LRU缓存算法:原理、应用与优化

LRU算法&#xff08;Least Recently Used&#xff0c;最近最少使用算法&#xff09;的思想是基于"时间局部性"原理&#xff0c;即在一段时间内&#xff0c;被访问过的数据在未来仍然会被频繁访问的概率较高。 LRU 原理 LRU算法的主要思想是将最近被使用的数据保留在…