zoukankan      html  css  js  c++  java
  • mybatis源码分析(5)-----拦截器的实现原理(动态代理+责任链)

    写在前面

      MyBatsi 的拦截器模式是基于代理的代理模式。并且myBatis 的插件开发也是以拦截器的形式集成到myBatis 当中。

      MyBatis 的拦截器已经插件是在org.apache.ibatis.plugin包下面。

      MyBatis拦截器可以拦截的类,Executor(执行器),ParameterHandler(参数处理器),ResultSetHandler(结果集处理器),StatementHandler(句处理器)。

    本文以Executor的插件为例子,来说明MyBatis 插件的工作原理

     1.首先分析 产生执行器Excutor 的代码

       通过interceptorChain的拦截器链,当一个执行器有过个拦截器,回产生拦截器链,也就是多重代理对象

       Configuration.java 文件
    //产生执行器 public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; //这句再做一下保护,囧,防止粗心大意的人将defaultExecutorType设成null? executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; //然后就是简单的3个分支,产生3种执行器BatchExecutor/ReuseExecutor/SimpleExecutor 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); } //如果要求缓存,生成另一种CachingExecutor(默认就是有缓存),装饰者模式,所以默认都是返回CachingExecutor if (cacheEnabled) { executor = new CachingExecutor(executor); } //此处调用插件,通过插件可以改变Executor行为 executor = (Executor) interceptorChain.pluginAll(executor); return executor; }

        Executor 执行器采用了模板方法模式。 

        Executor是执行器调度的核心。SqlSesson对外提供的api 其实就是 对于Executor 的调用(API-->SqlSesson-->Executor-->Statment-->DB)

      模板方法模式(解释):

         Executor 接口提供了query、update、commit、rollback 等方法。

         实现类BaseExecutor 给予基本的实现,在执行目标之前和之后 做了相关的处理(模板),且提供了实现具体操作的抽象方法。使得具体实现类SimpleExecutor、BatchExecutor、ReuseExecutor关注具体方法的实现。

         SimpleExecutor,BatchExecutor、ReuseExecutor 只需要实现自己的具体操作 doQuery、doUpdate、doCommit、doRollBack.

    Executor executor = new SimpleExecutor();  
    executor .query();

     2 其实Plugin采用了,插件,用的代理模式。自己实现了InvocationHandler接口,维护了目标类target和一个目标拦截器interceptor  

    public class Plugin implements InvocationHandler {
    
      private Object target;
      private Interceptor interceptor;
      private 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;
      }
    
      public static Object wrap(Object target, Interceptor interceptor) {
        //取得签名Map
        Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
        //取得要改变行为的类(ParameterHandler|ResultSetHandler|StatementHandler|Executor)
        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;
      }
    
      @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)) {
            //调用Interceptor.intercept,也即插入了我们自己的逻辑
            return interceptor.intercept(new Invocation(target, method, args));
          }
          //最后还是执行原来逻辑
          return method.invoke(target, args);
        } catch (Exception e) {
          throw ExceptionUtil.unwrapThrowable(e);
        }
      }
    }

    myBatis 中用到的设计模式

    一、建造者模式

    BaseBuilder、XMLMapperBuilder、SQlSessionFactoryBuilder

    二、工厂方法

    SqlSessionFactory、TranscationFactory、MapperProxyFactory

    三、模板方法模式

    Executor、StatmentHandler

    四、动态代理

    Plugin、SqlSessionTemplate、MapperProxy

    五、责任链模式

    Interceptor、InterceptorChain

      

  • 相关阅读:
    最大子数组问题(分治策略实现)
    Solving the Detached Many-to-Many Problem with the Entity Framework
    Working With Entity Framework Detached Objects
    Attaching detached POCO to EF DbContext
    如何获取qq空间最近访问人列表
    Health Monitoring in ASP.NET 2.0
    problem with displaying the markers on Google maps
    WebMatrix Database.Open… Close() and Dispose()
    Accessing and Updating Data in ASP.NET: Retrieving XML Data with XmlDataSource Control
    Create web setup project that has crystal reports and sql script run manually on client system
  • 原文地址:https://www.cnblogs.com/chihirotan/p/6679139.html
Copyright © 2011-2022 走看看