1.Mybatis-Plugin的设计思路

听起来一个挺神奇的单词,插件。说白了就是使用了Jdk自带的动态代理.在需要的时候进行代理。AOP怎么用,他就怎么用。

Plugin类等价于InvocationHandler.Mybatis在调用Jdk代码如下:

 Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));

Plugin类继承InvocationHandler接口

public class Plugin implements InvocationHandler {

  private final Object target;
private final Interceptor interceptor;
private final Map<Class<?>, Set<Method>> signatureMap; private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
this.target = target;
this.interceptor = interceptor;
this.signatureMap = signatureMap;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

invoke方法执行的时候,也就是intercept被调用的时候.

用一句成语来讲,借鸡下蛋。借尸还魂(这个词还有点吓人)

2.写一个例子.使用Intecept接口,但不应用在Mybatis框架内。

思路:① 写一个接口+一个类②写一个Inteceptor对该接口进行增强。

--------------------接口----------------------------------

package org.mybatis.example.plugin;

public interface HelloWorld {

    void sayHello(Integer v);
}

-------------------实现类---------------------------------

package org.mybatis.example.plugin;

public class HelloWorldImpl implements HelloWorld {

    public void sayHello(Integer v){
System.out.println("Hello World!");
} public static void main(String[] args) { PluginUsedWithoutMyBatis plugin = new PluginUsedWithoutMyBatis(); HelloWorld helloWorld = (HelloWorld) plugin.plugin(new HelloWorldImpl()); helloWorld.sayHello(1);
}
}

--------------------Interceptor-----------------------------------

@Intercepts(@Signature(type= HelloWorld.class,method="sayHello",args={Integer.class}))
public class PluginUsedWithoutMyBatis implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable { String methodName =invocation.getMethod().getName(); Object result =null;
if(methodName.equals("sayHello")){ System.out.println("method Begin:"); result =invocation.proceed();
System.out.println("method Begin:");
}else{
result =invocation.proceed();
} return result;
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target,this);
} @Override
public void setProperties(Properties properties) { } public static void main(String[] args) { }
}

执行HelloWorldImpl中的Main方法,得到一段朴素的代码增强结果。

method Begin:
Hello World!
method Begin:

PluginUsedWithoutMyBatis类中需要注意的:

@Intercepts、@Signature这两个注解,限定了可以增强的接口,以及方法名称以及参数。
理解成过滤器。在Mybatis的Plugins配置中,所有的Plugin都配置在一起。根据Signature决定Interceptor对谁增强。

问题:

如果两个Interceptor都对同一个对象增强,结果如何?

写了另外一个代理类,对HelloWorldImpl进行二次增强,结果如下:

enhance Second Begin:
enhance First Begin:
Hello World!
enhance First end:
enhance Second end:

可以看到两次增强的结果。

3、回到Mybatis,是否可以对所有的MyBatis接口增强?

Mybatis的Configruation类,只在几个对象的创建时做了增强

StatementHandler 、ResultSetHandler 、ParameterHandler 、Executor 
  public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
} public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
ResultHandler resultHandler, BoundSql boundSql) {
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
return resultSetHandler;
} public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
} public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}

4、现有增强插件的实现:

Executor的query、update时候可以监控sql执行时间。监控慢SQL
Executor的query、update catch异常,当发生异常时,可以打印sql以及执行参数。以及具体错误消息。

mybatis的plugin的更多相关文章

  1. Mybatis插件Plugin

    Mybatis开源Plugin中最熟知的pagehelper,重点made in China 很多人开始用pagehelper时候,肯定很纳闷,以mysql为例,明明没有加limit语句,为什么打印出 ...

  2. Mybatis辅助神器-MyBatis Log Plugin

    1. 问题描述 Java操作数据库的两台流行天王-mybatis和hibernate,mytabis和hibernate的区别不想废话了,以前用hibernate,最近几年一直用的mybatis,目前 ...

  3. IDEA优秀插件分享之---Mybatis Log Plugin

    小伙伴们在使用mybatis的时候有时候会出现一些sql异常,这个时候就需要对执行的sql语句进行检查.然而mybatis一般使用log4j打印执行的sql语句,类型下面这种的: 这个时候如果sql语 ...

  4. Mybatis Log plugin 破解!!!

    前言 今天重新装了IDEA2020,顺带重装了一些插件,毕竟这些插件都是习惯一直在用,其中一款就是Mybatis Log plugin,按照往常的思路,在IDEA插件市场搜索安装,艹,眼睛一瞟,竟然收 ...

  5. Mybatis log plugin 破解!!!

    前言 今天重新装了IDEA2020,顺带重装了一些插件,毕竟这些插件都是习惯一直在用,其中一款就是Mybatis Log plugin,按照往常的思路,在IDEA插件市场搜索安装,艹,眼睛一瞟,竟然收 ...

  6. 我常用的插件之“Mybatis Log plugin”sql日志格式转化

    前言 今天重新装了IDEA2020,顺带重装了一些插件,毕竟这些插件都是习惯一直在用,其中一款就是Mybatis Log plugin,按照往常的思路,在IDEA插件市场搜索安装,艹,眼睛一瞟,竟然收 ...

  7. 互联网轻量级框架SSM-查缺补漏第八天(MyBatis插件plugin使用及原理)

    简言:今天进行第八天的记录(只是写了八天).有的时候看的多,有的时候看的少,看的少的时候就攒几天一起写了.而今天这个插件我昨天写了一下午,下班没写完就回去了,今天把尾收了,再加上一个过程图方便下面原理 ...

  8. Mybatis之plugin插件设计原理

    大多数框架,都支持插件,用户可通过编写插件来自行扩展功能,Mybatis也不例外. 我们从插件配置.插件编写.插件运行原理.插件注册与执行拦截的时机.初始化插件.分页插件的原理等六个方面展开阐述. 一 ...

  9. 【Mybtais】Mybatis 插件 Plugin开发(一)动态代理步步解析

    需求: 对原有系统中的方法进行'拦截',在方法执行的前后添加新的处理逻辑. 分析: 不是办法的办法就是,对原有的每个方法进行修改,添加上新的逻辑:如果需要拦截的方法比较少,选择此方法到是会节省成本.但 ...

随机推荐

  1. iOS11自定义导航条上移处理

    image.png 在自定义导航条时,通常会继承系统的UINavigationBar,但如上图,在iOS11上,导航条改动了.自定义导航条代码 -(MBNavigationBar *)myNavBar ...

  2. iis7 绑定多个ssl证书

    默认情况下iis上只能绑定一个ssl证书,如果多的话 会只认一个. 停止IIS 运行[ CMD]  ,  输入 [iisreset /STOP] 第一步:修改配置文件. 然后打开:C:/Windows ...

  3. Ubuntu系统下Anaconda使用方法总结

    前言:个人认为Anaconda比pip使用起来要方便很多,因为它创建虚拟环境和下载各种库都很方便.但是有时候conda的安装方法中没有某些库,必须使用pip来进行安装.所以,主要用Anaconda,偶 ...

  4. ECDSA host key for 192.168.0.101 has changed and you have requested strict checking.

    原文地址:http://blog.csdn.net/ausboyue/article/details/52775281 Linux SSH命令错误:ECDSA host key "ip地址& ...

  5. css flex方法标题左右两边平衡线

    <html> <div class="title"> <div class="line"></div> < ...

  6. SpringSecurity身份验证基础入门

    对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache Shiro.Spring Security). pom.xm ...

  7. [经验分享] MySQL Innodb表导致死锁日志情况分析与归纳【转,纯学习】

    在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志. 两个sql语句如下: (1)insert into backup_ta ...

  8. 用js简单实现一下迪克斯特拉算法

    今天看书看到了迪克斯特拉算法,大概用js实现一下呢,计算最短路径. 首先,迪克斯特拉算法只适用于有向无环图,且没有负权重,本例关系图如下哦,数字为权重,emmmm,画得稍微有点丑~ //大概用js实现 ...

  9. 1.使用脚本控制模型的移动 --《Unity 3D 游戏开发》笔记

    由于最新版的unity已经不支持javascript语言啦,本人又是个C#小白,所以记录一下自己写的脚本. first 创建一个模型,放在平面上,调整下角度,就像这样: 然后写一个脚本来控制模型移动: ...

  10. c#函数地址传入c++

    c# private delegate void ValidateEvent(int eventCode); private static void ValidateEventCallback(int ...