加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

Mybatis超详细插件机制解析,弄懂拦截器So easy

发布时间:2019-12-26 20:10:27 所属栏目:MySql教程 来源:站长网
导读:副标题#e# 概述 Mybatis插件又称拦截器,本篇文章中出现的拦截器都表示插件。 Mybatis采用责任链模式,通过动态代理组织多个插件(拦截器),通过这些插件可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插

如果有N个插件,就有N个代理,每个代理都要执行上面的逻辑。这里面的层层代理要多次生成动态代理,是比较影响性能的。虽然能指定插件拦截的位置,但这个是在执行方法时动态判断,初始化的时候就是简单的把插件包装到了所有可以拦截的地方。

因此,在编写插件时需注意以下几个原则:

不编写不必要的插件;

实现plugin方法时判断一下目标类型,是本插件要拦截的对象才执行Plugin.wrap方法,否者直接返回目标本身,这样可以减少目标被代理的次数。

// 假如我们只要拦截Executor对象,那么我们应该这么做 

public Object plugin(final Object target) { 

  if (target instanceof Executor) { 

   return Plugin.wrap(target, this); 

  } else { 

   return target; 

  } 

Mybatis插件很强大,可以对Mybatis框架进行很大的扩展。当然,如果你不理解Mybatis插件的原理,开发起来只能是模拟两可。在实际开发过程中,我们可以参考别人写的插件。下面是一个Mybatis分页的插件,可以为以后开发做参考。

/** 

 * Mybatis - 通用分页插件(如果开启二级缓存需要注意) 

 */ 

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}), 

    @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})}) 

@Log4j 

public class PageHelper implements Interceptor { 

 

  public static final ThreadLocal<Page> localPage = new ThreadLocal<Page>(); 

 

  /** 

   * 开始分页 

   * 

   * @param pageNum 

   * @param pageSize 

   */ 

  public static void startPage(int pageNum, int pageSize) { 

    localPage.set(new Page(pageNum, pageSize)); 

  } 

 

  /** 

   * 结束分页并返回结果,该方法必须被调用,否则localPage会一直保存下去,直到下一次startPage 

   * 

   * @return 

   */ 

  public static Page endPage() { 

    Page page = localPage.get(); 

    localPage.remove(); 

    return page; 

  } 

 

  public Object intercept(Invocation invocation) throws Throwable { 

    if (localPage.get() == null) { 

      return invocation.proceed(); 

    } 

    if (invocation.getTarget() instanceof StatementHandler) { 

      StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); 

      MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler); 

      // 分离代理对象链(由于目标类可能被多个插件拦截,从而形成多次代理,通过下面的两次循环 

      // 可以分离出最原始的的目标类) 

      while (metaStatementHandler.hasGetter("h")) { 

        Object object = metaStatementHandler.getValue("h"); 

        metaStatementHandler = SystemMetaObject.forObject(object); 

      } 

      // 分离最后一个代理对象的目标类 

      while (metaStatementHandler.hasGetter("target")) { 

        Object object = metaStatementHandler.getValue("target"); 

        metaStatementHandler = SystemMetaObject.forObject(object); 

      } 

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读