Mybatis高级【一】

本文详细分析了Mybatis的源码,涉及日志模块、数据源模块、缓存模块和反射模块。日志模块使用了适配器和代理模式,数据源模块采用了工厂模式,缓存模块利用装饰器模式实现,而反射模块则涉及对象创建和属性赋值。文章深入探讨了设计模式在Mybatis中的应用,如代理模式用于日志记录,工厂模式用于数据源管理,装饰器模式用于缓存功能的扩展。
摘要由CSDN通过智能技术生成

一、源码分析概述

目录

一、源码分析概述

mybatis架构分析​编辑

谈谈设计模式的原则:

二、日志模块分析

2.1、基础支撑层源码分析—日志模块,使用的设计模式:适配器模式、代理模式

2.2、适配器模式

代理模式那些事:

为什么使用代理模式?

三、数据源模块分析

3.1、基础支撑层源码分析 数据源模块需求。使用的设计模式:工厂模式

3.2、数据源模块类图

PooledDataSource获取和归还连接过程

3.3、工厂模式

四、缓存模块分析

4.1、基础支撑层源码分析 缓存模块需。使用的设计模式:装饰器模式

4.2、装饰器模式:

4.3、装饰器模式使用举例

五、反射模块分析

反射的核心类:


mybatis架构分析

包分析 详见脑图:java学习/享学架构师课程/03.mybaits/mybatis源码结构.xmind

谈谈设计模式的原则:

  • 单一职责原则:一个类或者一个接口只负责唯一项职责,尽量设计出功能单一的接口。
  • 依赖倒转原则:高层模块不应该依赖底层模块具体实现,接口高层与底层。既面向接口编程,当实现发生变化时,只需提供新的实现类,不需要修改高层模块代码。
  • 开放-封闭原则:程序对外扩展开放,对修改关闭,换句话说,当需求发生变化时,我们可以通过添加新模块来满足新需求,而不是通过修改原来的是现代码来满足新需求。

高级开发:面向接口编程

二、日志模块分析

2.1、基础支撑层源码分析—日志模块,使用的设计模式:适配器模式、代理模式

    • Mybatis没有提供日志的实现类,需要接入第三方日志组件,但第三方日志组件都有各自的log级别,且各不相同,mybatis统一提供了trace、debug、warn、error四个级别(适配器模式解决)

mybatis中,对应日志组件的实现类,如log4jImpl,就是log4j的适配器。在logging包中。

    • 自动扫描日志实现,并且第三方日志插件加载优先级如下,slf4j->commonsLogin->Log4J2->Log4j->JdkLog
    • 日志的使用要优雅的嵌入到主体功能中(代理模式,动态代理解决)

2.2、适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁,将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

Target:目标角色,期待得到的接口

Adaptee:适配者角色,被适配的接口

adapter:适配器角色,将源接口转换成目标接口

适用场景:当调用双方都不太容易修改的时候,为了复用现有组件可以使用适配器模式,在系统中接入第三方组件的时候经常被用到。

注意:如果系统中存在过多的适配器,会增加系统的复杂性,设计人员应考虑对系统进行重构。

 mybatis中适配器的使用

代理模式那些事:

定义:给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用

目的:

1、通过因考入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来不必要的复杂性;

2、通过代理对象对原有的业务增强;

为什么使用代理模式?

代理模式给我们带来的便利:

作为中介解耦客户端和真实对象,保护真实对象安全;

防止直接访问目标对象给系统带来不必要的复杂性;

对业务进行增强,增强点多样化;(AOP)

 

 

 

Connection代理对象(connectionLogger)能够返回一个prepareStatement的代理对象(prepareStatementLogger),让prepareStatement也具备日志能力打印参数;

prepareStatement的代理对象(prepareStatementLogger)能够返回一个resultSet的代理对象(ResultSetLogger),让resultSet也具备日志打印能力;

simpleExcutor类才是真正访问数据库的类

org.apache.ibatis.executor.SimpleExecutor的doQuery方法

org.apache.ibatis.executor.SimpleExecutor#prepareStatement方法生成Statement

我们可以看到,getConnection(statementLog)方法里是用connection的代理对象connectionLogger进行连接初始化的

private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Connection connection = this.getConnection(statementLog);
    Statement stmt = handler.prepare(connection, this.transaction.getTimeout());
    handler.parameterize(stmt);
    return stmt;
}
protected Connection getConnection(Log statementLog) throws SQLException {
    Connection connection = this.transaction.getConnection();
    return statementLog.isDebugEnabled() ? ConnectionLogger.newInstance(connection, statementLog, this.queryStack) : connection;
}

三、数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值