聊聊Mybatis的插件接口之责任链模式

举报
周杰伦本人 发表于 2022/08/30 21:08:40 2022/08/30
【摘要】 聊聊Mybatis的插件接口之责任链模式 拦截器接口 自定义拦截器 配置拦截器 总结 聊聊Mybatis的插件接口之责任链模式Mybatis定义了插件接口来用于扩展拦截 拦截器接口Interceptor接口:public interface Interceptor { Object intercept(Invocation invocation) throws Throwable; d...

聊聊Mybatis的插件接口之责任链模式

Mybatis定义了插件接口来用于扩展拦截

拦截器接口

Interceptor接口:

public interface Interceptor {
  Object intercept(Invocation invocation) throws Throwable;

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

  default void setProperties(Properties properties) {
  }

}

自定义拦截器

我们可以实现Interceptor接口来做拦截

@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {
                MappedStatement.class, Object.class, RowBounds.class,
                ResultHandler.class}),
        @Signature(type = Executor.class, method = "close", args = {boolean.class})
})
public class XppPlugin implements Interceptor {
    
}

类上的注解@Intercepts表示这个类是拦截器类,@Signature定义需要拦截的类,方法,方法对应参数,像我们定义的这个类拦截的方法就是Executor 接口中的 query(MappedStatement, Object, RowBounds, ResultHandler) 方法和 close(boolean) 方法。

配置拦截器

定义完拦截器之后,我们还需要在全局配置文件中配置这个拦截器

<plugins>
  <plugin interceptor="org.mybatis.example.XppPlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins>

<plugin>节点解析成Interceptor对象保存在Configuration.interceptorChain对象中

InterceptorChain是构建Interceptor责任链的类,通过遍历每个拦截器,调用拦截器的plugin()方法处理目标对象

public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
  }

plugin()中调用Plugin.wrap(target, this);来生成代理对象,Plugin 实现 InvocationHandler接口来作为代理类

具体wrap方法 的逻辑:

  1. 调用getSignatureMap()方法解析@Signature注解定义的方法集合
  2. 如果当前对象在注解定义的方法集合中,就通过Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap));创建代理对象
  3. invoke()方法中如果给定的方法在signatureMap集合中,就调用拦截器进行拦截处理,调用Interceptor的intercept()方法

这样Mybatis的plugin包下的类差不多就介绍完了

总结

我们总结一下,Mybatis定义了Interceptor拦截器接口,需要自定义拦截器的话实现这个接口,自定义拦截器类上通过@Intercepts注解和@Signature注解配置需要拦截的类的方法,并在全局配置文件中配置好我们自定义的类,InterceptorChain是责任链类,它的pluginAll()方法中遍历定义的拦截器一个一个处理目标对象,而拦截器的plugin()方法中调用Plugin类的wrap()生成代理对象,Plugin实现InvocationHandler接口利用JDK动态代理来创建对象,重写invoke方法,当前方法如果在@Signature注解中,就在执行具体方法前执行拦截器的intercept()方法

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。