원리의 MyBatis 플러그 - 책임과 동적 프록시의 체인을 반영

@

사용자 정의 인터셉터를 가지고하지 않은 경우, 당신은 나의 볼 수 있습니다 이전 기사를 . 당신은 JDK 동적 프록시를 사용하는 방법을 모르는 경우,이 볼 수있는 기사를 . 책임의 디자인 패턴의 체인이 이해하기 매우 간단합니다, 당신은 예를 찾을 수 온라인으로 볼 수 있습니다.

mybatis 달성하기 위해 동적 에이전트 및 책임의 체인을 사용하는 원리 플러그.

어느 한 방법을 인터셉트 할

에서 앞에 말했다, 당신은 코멘트 수 InteceptsSignature어떤 방법 차단을 지정할 수 있습니다. 그러나, 모든 방법이 차단 될 수 있음을 의미하지 않는다.

메소드의 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하는 방법.

이 방법은 에이전트

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에이전트의 마지막 층 후 프록시 개체를 반환하는 방법을. 여기에 에이전트의 층에주의를 기울이십시오.

A, B, C 세 인터셉터 (동일한 서명),이 경우, 층이 봉입되어있는 경우. 실행될 때, 마지막으로는 A> B> C> target.proceed ()> C> B> A.이며

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