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

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

目录

本文导读

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

[1. 工厂模式(Factory Pattern)](#1. 工厂模式(Factory Pattern))

[2. 单例模式(Singleton Pattern)](#2. 单例模式(Singleton Pattern))

[3. 建造者模式(Builder Pattern)](#3. 建造者模式(Builder Pattern))

[4. 代理模式(Proxy Pattern)](#4. 代理模式(Proxy Pattern))

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

[6. 策略模式(Strategy Pattern)](#6. 策略模式(Strategy Pattern))

[7. 观察者模式(Observer Pattern)](#7. 观察者模式(Observer Pattern))

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

[工厂模式的应用 - SqlSessionFactory](#工厂模式的应用 - SqlSessionFactory)

[单例模式的应用 - SqlSessionFactory](#单例模式的应用 - SqlSessionFactory)

[代理模式的应用 - Mapper动态代理](#代理模式的应用 - Mapper动态代理)

[建造者模式(Builder Pattern)](#建造者模式(Builder Pattern))

[策略模式 - Strategy Pattern](#策略模式 - Strategy Pattern)

[观察者模式 - Observer Pattern](#观察者模式 - Observer Pattern)

三、MyBatis源码解析

[工厂模式 - SqlSessionFactoryBuilder](#工厂模式 - SqlSessionFactoryBuilder)

[单例模式 - SqlSessionFactory](#单例模式 - SqlSessionFactory)

[代理模式 - MapperProxyFactory](#代理模式 - 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对象。

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

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

单例模式的应用 - SqlSessionFactory

实现原理:

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

java 复制代码
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动态生成的代理类。

java 复制代码
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等都有各自的实现,这正是模板方法模式的典型应用。

java 复制代码
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等,开发人员可以根据需要选择或自定义缓存策略,这体现了策略模式的灵活性。

java 复制代码
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能够在运行时灵活地扩展功能,体现了观察者模式的特点。

java 复制代码
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的过程是工厂模式的一个典型应用。

java 复制代码
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的单例实现,但在实际应用中,开发者通常会将其实现为单例模式,以下是一个简单的示例:

java 复制代码
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接口生成代理对象,以便拦截接口方法的调用。

java 复制代码
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核心技术 |

相关推荐
lllsure4 分钟前
MySQL总结
数据库·mysql
小白黑_21611 分钟前
设计模式笔记
笔记·设计模式
哎呀呀嗯呀呀16 分钟前
class 031 位运算的骚操作
java·算法·位运算
2401_8581205319 分钟前
古典舞在线交流平台:SpringBoot设计与实现详解
java·spring boot·后端
大白飞飞27 分钟前
IDEA创建、导入、删除maven项目
java·maven·intellij-idea
赐你岁月如歌31 分钟前
如何使用ssm实现基于web的网站的设计与实现+vue
java·后端·ssm
weixin_5318042444 分钟前
SQL优化技巧(如查询优化、索引优化)。分布式系统的基本概念及挑战(如数据一致性、服务发现、负载均衡)
数据库·sql·服务发现
凯子坚持 c1 小时前
C语言复习概要(四)
c语言·开发语言
何陈陈1 小时前
【Linux】线程池
linux·服务器·开发语言·c++
清风玉骨1 小时前
Qt-QHBoxLayout布局类控件(42)
开发语言·qt