通过 MyBatis 提供的弱小机制,应用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦挡的办法签名即可。

     @Slf4j@Intercepts({        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}        ),        @Signature(                type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}        ),        @Signature(                type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}        ),        @Signature(                type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}        ),})@Component@Order(-2)public class CustomizeInterceptor implements Interceptor {    @Override    public Object plugin(Object target) {        return Plugin.wrap(target, this);    }    @Override    public Object intercept(Invocation invocation) throws Throwable {        //获取代理对象        log.info("拦挡:{}", invocation.getMethod().getName());        return invocation.proceed();    }}
  1. MybatisConfiguration 中源码解析办法
     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 MybatisBatchExecutor(this, transaction);        } else if (ExecutorType.REUSE == executorType) {            executor = new MybatisReuseExecutor(this, transaction);        } else {            executor = new MybatisSimpleExecutor(this, transaction);        }        if (cacheEnabled) {            executor = new MybatisCachingExecutor(executor);        }        //插件拦截器链        executor = (Executor) interceptorChain.pluginAll(executor);        return executor;        }        }    
  1. InterceptorChain 中拦截器链条
     private final List<Interceptor> interceptors = new ArrayList<>();      public Object pluginAll(Object target) {        for (Interceptor interceptor : interceptors) {        //调用          target = interceptor.plugin(target);        }        return target;      }      //调用接口      default Object plugin(Object target) {      return Plugin.wrap(target, this);    }

3.它又持续调用了Plugin的静态方法wrap

   public static Object wrap(Object target, Interceptor interceptor) {   //获取签名办法    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);    Class<?> type = target.getClass();    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);    if (interfaces.length > 0) {    //生成代理对象 动静代理 调用invoke      return Proxy.newProxyInstance(          type.getClassLoader(),          interfaces,          new Plugin(target, interceptor, signatureMap));    }    return target;  }      

4.执行 拦挡

   @Override  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    try {      Set<Method> methods = signatureMap.get(method.getDeclaringClass());      if (methods != null && methods.contains(method)) {      //调用拦挡办法        return interceptor.intercept(new Invocation(target, method, args));      }      return method.invoke(target, args);    } catch (Exception e) {      throw ExceptionUtil.unwrapThrowable(e);    }  }    
  1. 流程图

最终Executor不再是原来的类,而是它的代理类。newStatementHandler办法和newResultSetHandler办法的流程,也差不多,最终也是生成代理类

6.当Executor、StatementHandler、ParameterHandler、ResultSetHandler执行他们本人的办法时,实际上调用他们的代理类Plugin中的invoke办法

7.多个plugins 拦截器代理 后面的代理类被前面的拦截器又代理
套娃行为

所以,前面的将会代理后面的,——越外层的越先执行

8.多个插件的执行程序曾经明了了,那么插件外面办法的执行程序呢?

query->prepare->setParameters->handleResultSets

这个博客还是讲的很分明的

参考博客:https://blog.csdn.net/qq_18433441/article/details/84036317