Принцип mybatis плагин - отражает цепочку ответственности и динамических прокси

@

Если вы не имели собственный перехватчик, вы можете увидеть мою предыдущую статью . Если вы не знаете , как использовать JDK динамического прокси, я вижу эту статью . Цепь ответственность шаблона проектирования очень проста для понимания, вы можете посмотреть в Интернете , чтобы найти примеры.

mybatis Подключите принцип использования динамического агента и цепочки ответственности достичь.

1, какие методы для перехвата

В передней части Said, вы можете прокомментировать Inteceptsи Signatureуказать , какой метод перехвата. Однако, это вовсе не означает , что все методы могут быть перехвачены.

Метод mybatis перехватчик перехвачена, существуют следующие типы:

1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
2. ParameterHandler (getParameterObject, setParameters)
3. ResultSetHandler (handleResultSets, handleOutputParameters)
4. StatementHandler (prepare, parameterize, batch, update, query)

Почему эти методы могут перехватить его?

В mybatisприведенных выше нескольких классах SqlSessionчетыре объекта. SqlSessionЭти цели достигаются за счет работы с базой данных, в результате обработки. Таким образом, в процессе, метод для перехвата этих объектов является очень важной ролью.
Объекты конфигурации в
И это находит свое отражение в исходном коде, в Configurationклассе, значение этого класса не делать слишком много экспозиции, вы можете увидеть предыдущую статью.

Xml разбирается в общий Configurationпроцесс, потребность в более чем несколько нового класса. Выше перезвонит в нескольких классах interceptorChain#pluginAllметода.

2 Как агент

public class InterceptorChain {

  /**
   * 拦截器列表
   */
  private final List<Interceptor> interceptors = new ArrayList<>();

  public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
  }

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

  /**
   * 获取拦截器列表
   *
   * @return
   */
  public List<Interceptor> getInterceptors() {
    return Collections.unmodifiableList(interceptors);
  }

}

Можно видеть , что перехватчик будет вызывать все pluginпути , чтобы вернуть объект прокси после финальных слоев агентов. Обратите внимание на слои агентов здесь.

Если есть А, В, С три-перехватчик (та же подпись), в этом случае слои инкапсулируются. И, наконец, когда выполняются, то А> В> С> target.proceed)> С (> В> А.

Объект 3 прокси

InterceptorChainКаждый перехватчик будет вызывать pluginметод. Этот метод возвращает соответствующий объект прокси.

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

  /**
   * 执行拦截逻辑的方法
   *
   * @param invocation 调用信息
   * @return 调用结果
   * @throws Throwable 异常
   */
  Object intercept(Invocation invocation) throws Throwable;

  /**
   * 代理
   *
   * @param target
   * @return
   */
  Object plugin(Object target);

  /**
   * 根据配置来初始化 Interceptor 方法
   * @param properties
   */
  void setProperties(Properties properties);

}

Что pluginэто нам нужно достичь. Mybatis также дает нам очень удобный способ.

  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) {
      // 创建代理对象
      return Proxy.newProxyInstance(
              type.getClassLoader(),
              interfaces,
              new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }

Когда мы перепишем метод плагин, просто вызовите описанный выше метод может быть. Она возвращает Pluginобъект этого класса.

public class Plugin implements InvocationHandler
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      // 获取方法所在类中, 可以被拦截的所有的方法
      Set<Method> methods = signatureMap.get(method.getDeclaringClass());
      // 如果需要被拦截, 则调用 interceptor.intercept
      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);
    }
  }

Поскольку JDK динамического прокси является уровень интерфейса. Таким образом, агенты, все методы интерфейса класса. Однако, не все методы должны быть проксированными, поэтому, чтобы различать процесс подписи с помощью информации в примечаниях.

4 цепи ответственности шаблона проектирования

В процессе использования плагина, цепочка ответственность шаблона проектирования отражаются в динамическом прокси глубоко вложенный усовершенствование агента. Отраженный в interceptorChain#pluginAllметоде. Он призовет слои прокси. Принцип mybatis плагин - отражает цепочку ответственности и динамических прокси

рекомендация

отwww.cnblogs.com/homejim/p/11605228.html