Mybatis学习笔记(四)-Mybatis中自定义插件与实现原理

Scroll Down

Mybatis学习笔记(四)-Mybatis中自定义插件与实现原理

mybatis四大核心组件(Executor,StatementHandler,ParameterHandler,ResultSetHandler),mybatis为这四大组件提供了简单易用的插件扩展机制,mybatis对持久层的操作就是借助于四大核心对象,也支持用插件对四大核心对象进行拦截,使用拦截器来增强核心对象的功能,增强功能借助的是动态代理来实现的.

image-20200427102440159

mybatis允许的拦截方法如下:

  • 执行器Executor(update,query,commit,rollback等方法)
  • Sql语法构建起StatementHandler(prepare,paramterize,batch,update,query等方法)
  • 参数处理器ParamterHandler(getParameterObject,setParamters方法)
  • 结果集处理器ResultSetHandler(handleResultSets,handleOutputParameters等方法)

mybatis插件的原理

在四大对象创建的时候

  1. 每个创建出来的对象不是直接返回的,使用interceptorChain.pluginAll(parameterHandler)方法
  2. 获取所有的Interceptor(拦截器),调用interceptor.plugin(target)返回包装后的对象
  3. 插件机制,使用插件为目标创建一个代理对象,AOP我们的插件可以为四大对象创建出代理对象,代理对象可以拦截到四大对象的每一个执行

自定义mybatis拦截插件

写一个类实现Interceptor接口,其中@Signature(type = 拦截的class,method 是拦截的方法,args 是传入的参数)

@Intercepts 中可以定义多个Signature进行拦截

@Intercepts({
        @Signature(type= StatementHandler.class,
                  method = "prepare",
                  args = {Connection.class,Integer.class})
})
public class MyPlugin implements Interceptor {

    /*
        拦截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行intercept方法
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("对方法进行了增强前....");
        Object proceed = invocation.proceed();//原方法执行
        System.out.println("对方法进行了增强后....");
        return  proceed;
    }

    /*
       主要为了把当前的拦截器生成代理存到拦截器链中
     */
    @Override
    public Object plugin(Object target) {
        Object wrap = Plugin.wrap(target, this);
        return wrap;
    }

    /*
        获取配置文件的参数
     */
    @Override
    public void setProperties(Properties properties) {
        System.out.println("获取到的配置文件的参数是:"+properties);
    }
}

写完类之后要在xml中进行配置

<plugins>
       <plugin interceptor="com.lagou.plugin.MyPlugin">
            <property name="name" value="tom"/>
        </plugin>
</plugins>

执行结果为:

image-20200427110303767

mybatis插件的拦截原理

首先解析配置文件的时候,会去解析plugins配置下的数据,并将所有插件添加到
interceptorChain()拦截链当中

public class Configuration {
    //将所有的插件添加到interceptorChain()拦截链中
    public void addInterceptor(Interceptor interceptor) {
    	interceptorChain.addInterceptor(interceptor);
  	}
}

随后,在执行openSession()方法的通时,会将对应的插件进行一一执行,匹配到符合的插件,即生成一个新的动态代理对象并增加相应的方法

public class DefaultSqlSessionFactory implements SqlSessionFactory {

  private final Configuration configuration;

  public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }

  @Override
  public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }
}

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
        //新建一个执行器
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

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 BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    //在最终的执行器代码中,触发所有的插件,对相应的核心对象进行增强
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

  public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
  }
    @Override
    public Object plugin(Object target) {
	//返回动态代理对象或者原始对象
        Object wrap = Plugin.wrap(target, this);
        return 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) {
        //如果匹配到对应的类的话,返回一个新的代理对象,对方法进行增强
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }