6

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

 2 years ago
source link: https://blog.51cto.com/u_15460453/5615508
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

精选 原创

周杰伦本人 2022-08-24 12:02:53 ©著作权

文章标签 拦截器 自定义拦截器 java 文章分类 Java 编程语言 yyds干货盘点 阅读数219

Table of Contents

聊聊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责任链的类,通过遍历每个拦截器,调用lanjie器 的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()方法中遍历定义的拦截器一个一个处理目标对象,而lanjie器的plugin()方法中调用Plugin类的wrap()生成代理对象,Plugin实现InvocationHandler接口利用JDK动态代理来创建对象,重写invoke方法,当前方法如果在@Signature注解中,就在执行具体方法前执行lanjie器的intercept()方法

  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK