写点什么

Mybatis 源码分析二 - 如何优雅的使用主体日志,zookeeper 集群实现原理

用户头像
极客good
关注
发布于: 刚刚

角色代表含义:


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


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


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


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


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

2.1.2.MyBatis 日志模块适配器的使用

mybatis 的日志模块的主要实现如下:



  • Target:mybatis 中 org.apache.ibatis.logging.Log 扮演者 target 角色,用于对内提供统一的日志接口;

  • Adaptee:其他日志组件组件如 slf4J 、commonsLoging 、 Log4J2 等被包含在适配器中,用于被适配。

  • Adapter:针对每个日志组件都提供了适配器, 每 个 适 配 器 都 对 特 定 的 日 志 组 件 进 行 封 装 和 转 换 ,保证对外提供一同的使用标准。; 如 Slf4jLoggerImpl JakartaCommonsLoggingImpl 等;


mybatis 的日志模块实现采用适配器模式,日志组件(Target)、适配器以及统一接口(Log 接口) 定义清晰明确符合单一职责原则;同时,客户端在使用日志时,面向 Log 接口编程,不需要 关心底层日志模块的实现,符合依赖倒转原则;最为重要的是,如果需要加入其他第三方日 志框架,只需要扩展新的模块满足新需求,而不需要修改原有代码,这又符合了开闭原则。


2.2.日志组件顺序加载的实现




日志组件的顺序加载实现比较简单,mybatis 加载之后在静态代码块中完成的加载。不在过多讲解。



2.3.优雅的使用日志模块的实现




我们在打开 mybatis 日志的时候,无需任何多余的操作,只需将配置打开即可将看到执行日志。那么我们要实现优雅日志,首先我们得搞清楚,在什么情况下要打日志,通过我们对日志的使用,一般有如下几个位置需要进行日志打印


  1. 在创建 prepareStatement 时,打印执行的 SQL 语句;

  2. 访问数据库时,打印参数的类型和值

  3. 查询出结构后,打印结果数据条数


在 mbatis 的日志模块中有 BaseJdbcLogger、ConnectionLogger、PreparedStatementLogger 和 ResultSetLogge 通过动态代理负责在不同的位置打印日志;


说到动态代理那


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


么很显然,mybatis 的日子增强是通过代理模式进行实现的。那么我们了解下什么是代理模式。

2.3.1.代理模式

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



例如小王要买个化妆品,但是他不知道渠道,只能通过小张这个海外代购渠道去购买化妆品店。?因此小王不需要和化妆品店直接交互,由小张代理帮他购买即可。


主要目的:


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

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


代理模式有静态代理动态代理两种实现方式。?


静态代理?


这种代理方式需要代理对象和目标对象实现一样的接口。


优点:可以在不修改目标对象的前提下扩展目标对象的功能。


缺点:由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。不易维护。一旦接口增加方法,目标对象与代理对象都要进行修改。?


动态代理?


动态代理利用了 JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能。


动态代理又被称为 JDK 代理或接口代理。


静态代理与动态代理的区别主要


1. 静态代理在编译时就已经实现,编译完成后代理类是一个实际的 class 文件


2. 动态代理是在运行时动态生成的,即编译完成后没有实际的 class 文件,而是在运行时 动态生成类字节码,并加载到 JVM 中 注意:动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态 代理。?


JDK 中生成代理对象主要涉及两个类,第一个类为 java.lang.reflect.Proxy,通过静态方法 newProxyInstance 生成代理对象,第二个为 java.lang.reflect.InvocationHandler 接口,通过 invoke 方法对业务进行增强;?


2.4.Mybatis 日志模块实现分析



2.4.1.基础日志组件

刚才我们讲到 mybatis 的日志模块中有 BaseJdbcLogger、ConnectionLogger、PreparedStatementLogger 和 ResultSetLogge 通过动态代理负责在不同的位置打印日志;他们的类图如下:



BaseJdbcLogger:所有日志增强的抽象基类,用于记录 JDBC 那些方法需要增强,保存运 行期间 sql 参数信息;




ConnectionLogger:负责打印连接信息和 SQL 语句。通过动态代理,对 connection 进行 增强,如果是调用 prepareStatement、prepareCall、createStatement 的方法,打印要执 行的 sql 语句并返回 prepareStatement 的代理对象(PreparedStatementLogger),让 prepareStatement 也具备日志能力,打印参数;



用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Mybatis源码分析二-如何优雅的使用主体日志,zookeeper集群实现原理