Mybatis超详细插件机制解析,弄懂拦截器So easy
如果有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); } (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |