mybatis插件逻辑

自定义实现插件

自定义插件要实现mybatis的插件接口 Interceptor

public interface Interceptor {

  // 执行拦截逻辑的方法 
  Object intercept(Invocation invocation) throws Throwable;

  // 决定是否触发 intercept()方法,如果该插件是拦截对应方法,则返回该类的代理对象
  default Object plugin(Object target	) {
    return Plugin.wrap(target, this);
  }

  // 根据配置 初始化 Intercept 对象
  default void setProperties(Properties properties) {
    // NOP
  }

}

自定义拦截器
@Intercepts({
@Signature(
type = Executor.class // 需要拦截的类型
, method = “query” // 需要拦截的方法
// args 中指定 被拦截方法的 参数列表
, args = {MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class}
),
@Signature(
type = Executor.class
, method = “close”
, args = {boolean.class}
)
})
public class MyInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
System.out.println(“被拦截方法执行前打印。。。”);
Object object = invocation.proceed();
System.out.println(“被拦截方法执行后打印。。。”);
return object;

}

public Object plugin(Object target) {
    return Plugin.wrap(target, this);
}

public void setProperties(Properties properties) {

}

}

插件配置初始化

插件拦截的4个类:Excutor \ParameterHandler \ StatementHandler\ ResultSetHandler

<plugins>
   <plugin interceptor="com.yuz..MyInterceptor ">
     <property name="testProp" value="1000"/>
   </plugin>
  </plugins>

初始化
SqlSessionFactoryBuilder

  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
   try {
     // 读取配置文件
     XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
     // 解析配置文件得到Configuration对象 创建DefaultSqlSessionFactory对象
     return build(parser.parse());
   } catch (Exception e) {
     throw ExceptionFactory.wrapException("Error building SqlSession.", e);
   } finally {
     ErrorContext.instance().reset();
     try {
       reader.close();
     } catch (IOException e) {
       // Intentionally ignore. Prefer previous error.
     }
   }
 }

XMLConfigBuilder
插件解析:pluginElement(root.evalNode(“plugins”));,最终得到
InterceptorsChain 对象,里面对插件进行管理

private void parseConfiguration(XNode root) {
   try {
     //issue #117 read properties first
     // 对于全局配置文件各种标签的解析
     propertiesElement(root.evalNode("properties"));
     // 解析 settings 标签
     Properties settings = settingsAsProperties(root.evalNode("settings"));
     // 读取文件
     loadCustomVfs(settings);
     // 日志设置
     loadCustomLogImpl(settings);
     // 类型别名
     typeAliasesElement(root.evalNode("typeAliases"));
     // 插件
     pluginElement(root.evalNode("plugins"));
     // 用于创建对象
     objectFactoryElement(root.evalNode("objectFactory"));
     // 用于对对象进行加工
     objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
     // 反射工具箱
     reflectorFactoryElement(root.evalNode("reflectorFactory"));
     // settings 子标签赋值,默认值就是在这里提供的 >>
     settingsElement(settings);
     // read it after objectFactory and objectWrapperFactory issue #631
     // 创建了数据源 >>
     environmentsElement(root.evalNode("environments"));
     databaseIdProviderElement(root.evalNode("databaseIdProvider"));
     typeHandlerElement(root.evalNode("typeHandlers"));
     // 解析引用的Mapper映射器
     mapperElement(root.evalNode("mappers"));
   } catch (Exception e) {
     throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
   }
 }

InterceptorsChain

public class InterceptorChain {

 // 保存所有的 Interceptor  也就我所有的插件是保存在 Interceptors 这个List集合中的
 private final List<Interceptor> interceptors = new ArrayList<>();

 //根据拦截器集合的拦截配置对某一个对象的进行拦截(反射代理)
 public Object pluginAll(Object target) {
   for (Interceptor interceptor : interceptors) { // 获取拦截器链中的所有拦截器
     target = interceptor.plugin(target); // 创建对应的拦截器的代理对象
   }
   return target;
 }

 public void addInterceptor(Interceptor interceptor) {
   interceptors.add(interceptor);
 }

 public List<Interceptor> getInterceptors() {
   return Collections.unmodifiableList(interceptors);
 }

}

代理方法的执行 plugin

 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   try {
     // 获取当前方法所在类或接口中,可被当前Interceptor拦截的方法
     Set<Method> methods = signatureMap.get(method.getDeclaringClass());
     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);
   }
 }

插件的关键类

Interceptor :插件接口,用户自定义插件需要实现该接口
InterceptroChain :插件链管理:应用中所有的插件在初始化节点都会解析放到该对象中进行管理
Plugin :插件触发管理类,负责对插件对象进行代理包装,同时实现invoke调用逻辑,实现多个插件的层层调用
Invocation:调用方法的包装对象,封装调用方法的信息
@Interceptors 拦截的配置注解
@Signature :拦截方法签名注解

上一篇:python并行多个线程和进程


下一篇:程序环境和预处理2