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


    聊聊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) 方法。

    配置拦截器

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

    
      
        
      
    

    <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()方法

  • 相关阅读:
    MySQL 保姆级教程(一):了解 SQL
    Docker 摸门级简易手册
    depthimage-to-laserscan
    xshell对多个终端同时执行命令
    idea中maven自带Bundled (Maven 2)和Bundled (Maven 3)的文件目录位置
    如何用java 5分钟实现一个最简单的mysql代理服务器?
    解决这两个世界级难题,自动驾驶就能够实现超进化?
    Spring Data MongoDB中查询指定返回特定字段
    Vue框架实现对前端数据表的增删改查(第六课)
    lvs+keepalived: 高可用集群
  • 原文地址:https://blog.csdn.net/Candyz7/article/details/126518075