Mybatis-Interceptor源码解析

Mybatis3.5.1源码分析

  1. Mybatis-SqlSessionFactoryBuilder,XMLConfigBuilder,XPathParser源码解析
  2. Mybatis-Configuration源码解析
  3. Mybatis-事务对象源码解析
  4. Mybatis-数据源源码解析
  5. Mybatis缓存策略源码解析
  6. Mybatis-DatabaseIdProvider源码解析
  7. Mybatis-TypeHandler源码解析
  8. Mybatis-Reflector源码解析
  9. Mybatis-ObjectFactory,ObjectWrapperFactory源码分析
  10. Mybatis-Mapper各类标签封装类源码解析
  11. Mybatis-XMLMapperBuilder,XMLStatmentBuilder源码分析
  12. Mybatis-MapperAnnotationBuilder源码分析
  13. [Mybatis-MetaObject,MetaClass源码解析]https://www.jianshu.com/p/f51fa552f30a)
  14. Mybatis-LanguageDriver源码解析
  15. Mybatis-SqlSource源码解析
  16. Mybatis-SqlNode源码解析
  17. Mybatis-KeyGenerator源码解析
  18. Mybatis-Executor源码解析
  19. Mybatis-ParameterHandler源码解析
  20. Mybatis-StatementHandler源码解析
  21. Mybatis-DefaultResultSetHandler(一)源码解析
  22. Mybatis-DefaultResultSetHandler(二)源码解析
  23. Mybatis-ResultHandler,Cursor,RowBounds 源码分析
  24. Mybatis-MapperProxy源码解析
  25. Mybatis-SqlSession源码解析
  26. Mybatis-Interceptor源码解析

InterceptorChain

/**
 *    Copyright 2009-2019 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.plugin;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 拦截器链
 * @author Clinton Begin
 */
public class InterceptorChain {

  /**
   * 拦截器集合
   */
  private final List interceptors = new ArrayList<>();

  /**
   * 通知所有拦截器,通知所有拦截器对 {@code target} 进行个性化包装
   * @param target 目标对象
   * @return 经过所有拦截器进行个性化包装后的对象
   */
  public Object pluginAll(Object target) {
    //遍历所有拦截器
    for (Interceptor interceptor : interceptors) {
      //不断对target用拦截器包装再包装
      target = interceptor.plugin(target);
    }
    // 经过所有拦截器进行个性化包装后的对象
    return target;
  }

  /**
   * 添加拦截器
   * @param interceptor 拦截器
   */
  public void addInterceptor(Interceptor interceptor) {
    //将interceptor添加拦截器集合
    interceptors.add(interceptor);
  }

  /**
   * 返回拦截器集合
   * @return 不可修改的拦截器集合
   */
  public List getInterceptors() {
    //Collections.unmodifiableList返回的对象其实是interceptors,但是这个返回对象修改会抛出异常
    return Collections.unmodifiableList(interceptors);
  }

}

Interceptor

/**
 *    Copyright 2009-2015 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.plugin;

import java.util.Properties;

/**
 * 拦截器
 * 
 * @author Clinton Begin
 */
public interface Interceptor {

  /**
   * intercept:拦截
   * 拦截目标对象的目标方法的执行
   */
  Object intercept(Invocation invocation) throws Throwable;

  /**
   * 包装目标对象的:包装:为目标对象创建一个代理对象
   * @param target
   * @return
   */
  Object plugin(Object target);

  /**
   * setProperties:
   *      将插件注册时 的property属性设置进来
   */
  void setProperties(Properties properties);

}

拦截器的实现例子:

因为源码并没有比较好的示例,所以我上网找了一个
拦截器的实现例子

Plugin

/**
 *    Copyright 2009-2019 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.plugin;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.ibatis.reflection.ExceptionUtil;

/**
 * @author Clinton Begin
 */
public class Plugin implements InvocationHandler {

  /**
   * 目标对象
   */
  private final Object target;
  /**
   * 拦截器对象
   */
  private final Interceptor interceptor;
  /**
   * 目标类-方法集
   */
  private final Map, Set> signatureMap;

  /**
   *
   * @param target 目标对象
   * @param interceptor 拦截器
   * @param signatureMap 目标类-方法集
   */
  private Plugin(Object target, Interceptor interceptor, Map, Set> signatureMap) {
    this.target = target;
    this.interceptor = interceptor;
    this.signatureMap = signatureMap;
  }

  /**
   * 根据将 {@code interceptor} 的配置Intercepts注解信息 ,实现 {@code target} 的代理对象
   * 并返回出去,从而实现调用{@code interceptor}的intercept方法
   * @param target 目标对象
   * @param interceptor 拦截器
   * @return {@code target} 的代理对象,代理对象会回调Plugin的invoke方法,然后回调{@code interceptor}的intercept方法
   */
  public static Object wrap(Object target, Interceptor interceptor) {
    //将 interceptor 的配置Intercepts注解信息封装成存储拦截目标对象类,
    //以及拦截目标对象类的方法集映射关系的HashMap
    Map, Set> signatureMap = getSignatureMap(interceptor);
    //获取target的类型
    Class type = target.getClass();
    //获取type 的在signatureMap有所包含的所有接口类
    Class[] interfaces = getAllInterfaces(type, signatureMap);
    //如果interfaces不是空数组
    if (interfaces.length > 0) {
      //新建一个继承interfaces的代理对象
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }

  /**
   * 代理方法
   * @param proxy 目标对象
   * @param method 方法对象
   * @param args 参数对象数组
   * @return 方法对象的返回对象
   * @throws Throwable
   */
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      //获取声明method的类的指定方法集
      Set methods = signatureMap.get(method.getDeclaringClass());
      //如果方法集不为null且方法集包含method
      if (methods != null && methods.contains(method)) {
        //执行拦截器的intercept方法
        return interceptor.intercept(new Invocation(target, method, args));
      }
      //如果不是指定的方法,直接执行目标方法
      return method.invoke(target, args);
    } catch (Exception e) {
      //当e属于InvocationTargetException 和UndeclaredThrowableException的类型时,
      // 会从中 获取更加精确的异常抛出。
      throw ExceptionUtil.unwrapThrowable(e);
    }
  }

  /**
   * 将 {@code interceptor} 的配置Intercepts注解信息封装成存储拦截目标对象类,
   * 以及拦截目标对象类的方法集映射关系的HashMap
   * @param interceptor 拦截器
   * @return 一个存储拦截目标对象类,以及拦截目标对象类的方法集映射关系的HashMap
   */
  private static Map, Set> getSignatureMap(Interceptor interceptor) {
    //获取Intercepts注解
    Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
    // issue #251
    //如果拦截器没有配置Intercepts注解
    if (interceptsAnnotation == null) {
      //抛出异常
      throw new PluginException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName());
    }
    //获取Intercepts注解中的所有Signature注解
    Signature[] sigs = interceptsAnnotation.value();
    //新建一个HashMap,用于存储拦截目标对象类,以及拦截目标对象类的方法集
    Map, Set> signatureMap = new HashMap<>();
    //遍历Signature注解数组
    for (Signature sig : sigs) {
      //获取Signature注解中指定的拦截目标对象类对应的方法集
      Set methods = signatureMap.computeIfAbsent(sig.type(), k -> new HashSet<>());
      try {
        //获取拦截目标对象类中对应Signature注解配置方法和参数类型的方法对象
        Method method = sig.type().getMethod(sig.method(), sig.args());
        //将方法对象添加到方法集里
        methods.add(method);
      } catch (NoSuchMethodException e) {
        throw new PluginException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e, e);
      }
    }
    return signatureMap;
  }

  /**
   * 获取 {@code type} 的在 {@code signatureMap} 有所包含的所有接口类
   * @param type 目标对象类
   * @param signatureMap 存储拦截目标对象类,以及拦截目标对象类的方法集的HashMap
   * @return  {@code type} 的在 {@code signatureMap} 有所包含的接口类数组
   */
  private static Class[] getAllInterfaces(Class type, Map, Set> signatureMap) {
    //新建一个HashSet,用于保存type的在signatureMap包含的接口类
    Set> interfaces = new HashSet<>();
    //如果目标对象类不为null
    while (type != null) {
      //目标对象类的所有接口
      for (Class c : type.getInterfaces()) {
        //如果signatureMap中包含这个接口类
        if (signatureMap.containsKey(c)) {
          //将接口类添加到interfaces
          interfaces.add(c);
        }
      }
      //取出type的父类重新赋值给type
      type = type.getSuperclass();
    }
    //将interfaces集和转换成接口类数组
    return interfaces.toArray(new Class[interfaces.size()]);
  }

}

你可能感兴趣的:(Mybatis-Interceptor源码解析)