MyBatis拦截器–从基础到与Spring Boot整合

本文介绍了MyBatis拦截器的基础知识,包括如何配置和使用拦截器,以及如何与Spring Boot进行整合。文章详细讲解了拦截器的方法、注解以及在实际操作中的应用,如分页插件示例。最后提到了两种在Spring Boot中整合MyBatis拦截器的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MyBatis拦截器–从基础到与Spring Boot整合

前言

MyBatis拦截器是Java持久层框架,最近在研究拦截器的写法。本以为会很复杂,实际上从使用上来说,是很简单的.
本文主要介绍的时各个方法和注解的含义及使用方式,并且与Spring Boot进行简单的整合。
话不多说,开始说明。

关于拦截器

Mybatis拦截器的写法很简单,需要继承Interceptor类,重写其中的intercept()plugin()setProperties()

package org.apache.ibatis.plugin;

//import ingnore

public interface Interceptor {

  Object intercept(Invocation invocation) throws Throwable;

  Object plugin(Object target);

  void setProperties(Properties properties);

}

具体如下:

@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
@Component
public class UserAuthorityDataInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

这是先说方法,再说注解

方法
  • setProperties()方法主要是用来从配置中获取属性。

    如果是使用xml式配置拦截器,可在Mybatis配置文件中添加如下节点,属性可以以如下方式传递

    <plugins>
    	<plugin interceptor="tk.mybatis.simple.plugin.XXXInterceptor">
    		<property name="propl" value="valuel" />
    		<property name="prop2" value="value2" />
    	</plugin>
    </plugins>
    

    如果在Spring boot中使用,则需要单独写一个配置类,如下:

    @Configuration
    public class MybatisMapperAutoConfiguration{
        @Bean
        public void zipkinInterceptor(SqlSessionFactory sqlSessionFactory) {
            ZipkinInterceptor zipkinInterceptor = new ZipkinInterceptor();
            Properties properties = new Properties();
            properties.setProperty("prop1","value1");
            zipkinInterceptor.setProperties(properties);
            sqlSessionFactory.getConfiguration().addInterceptor(zipkinInterceptor);
        }
    }
    

    如果说不需要配置属性,则在spring boot中,不需要去编写配置类,只需要像我一样在拦截器上加个@Component即可。

  • plugin()方法用于指定哪些方法可以被此拦截器拦截。如下:

    @Override
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        }
        return target;
    }
    

    Plugin.wrap()是个包装方法,如果需要此拦截器,则将此此拦截器连同入参中的target一起包装后返回,如果不需要则直接返回target

    另附具体Plugin.wrap()的源码:

    public static Object wrap(Object target, Interceptor interceptor) {
      Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
      Class<?> type = target.getClass();
      Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
      if (interfaces.length > 0) {
        return Proxy.newProxyInstance(
            type.getClassLoader(),
            interfaces,
            new Plugin(target, interceptor, signatureMap));
      }
      return target;
    }
    
  • intercept()方法是用来对拦截的sql进行具体的操作。

    这里拿分页插件PageHelper中的类PageInterceptor进行说明。

    坐标:com.github.pagehelper.PageInterceptor#intercept(Invocation)

    intercept()方法

    1. invocation.getArgs()是从入参invocation获取拦截器所拦截方法的参数,其参数顺序和被拦截的方法保持一致,这个参数的个数以及参数具体是什么我们下一步说到@Signature注解时会讲。

    2. 获取执行器,可以用Executor直接执行被我们修改过的sql,示例如下

      返回值说明

      这里就是不继续执行原来的方法体中的内容,而是去执行我们修改后的sql并且返回。

    3. 关于返回值

      除了以上这种直接去执行我们修改过sql的方式,如果我们想让方法继续执行下去也是可以的。

      只需要返回:

      return invocation.proceed();
      
注解

MyBatis拦截器用到了两个注解:@Intercepts@Signature

  • @Intercepts

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface Intercepts {
      Signature[] value();
    }
    

    可以看到,其中是一个Signature类型的数组,意味着一个拦截器可以拦截多种方法。

  • @Signature

    Signature意为签名,署名。实际上作用也与语义相同:表明需要拦截方法的方法签名。

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Signature {
      Class<?> type();
    
      String method();
    
      Class<?>[] args();
    }
    

    有三个参数,

    • type:类型
    • method:方法名称
    • args:方法参数

    这三个参数可以确定一个方法。默认情况下, MyBatis允许使用插件(拦截器)来拦截的接口和包括以下几个。

    • Executor ( update 、 query 、 flushStatements 、 commit 、 rollback 、 get Transaction、 close、 isClosed)
    • ParameterHandler ( getParameterObj ect、setParameters)
    • ResultSetHandler ( handleResul tSets 、 handleCursorResultSets 、 handleOutputParameters)
    • StatementHandler (prepare、 parameterize、 batch、 update、 query)

    实际上,我们只需要记住这几个接口名称就可以,其余我们可以根据实际需要去看源码来确定具体所需要拦截的类。

    • Executorquery方法举例说明@Signature是如何确定一个方法。

    方法签名

    如果我们需要拦截第一个方法,只需要这么写@Signature

    @Signature(type = 
    			Executor.class, 
    			method = "query", 
    			args = {
    				MappedStatement.class, 
    				Object.class, 
    				RowBounds.class, 
    				ResultHandler.class, 
    				CacheKey.class, 
    				BoundSql.class
    				}
    )
    

    可以注意看,type的值与类名相同,method方法名相同,为了避免方法重载,args中指定了各个参数的类型和个数

    • 如果我们想拦截多个方法,比如说上图1和2的方法我们都想拦截到,只需要再加个@Signature就可以,要记得@Intercepts的value可是数组啊

    • @Intercepts(
              {
                      @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
                      @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
              }
      )
      
与Spring Boot整合

与Spring Boot整合这一块就简单许多,主要有两种方法,其实在上文中已有交代。

  1. 手写一个配置类

    @Configuration
    public class MybatisMapperAutoConfiguration{
        @Bean
        public void zipkinInterceptor(SqlSessionFactory sqlSessionFactory) {
            ZipkinInterceptor zipkinInterceptor = new ZipkinInterceptor();
            Properties properties = new Properties();
            properties.setProperty("prop1","value1");
            zipkinInterceptor.setProperties(properties);
            sqlSessionFactory.getConfiguration().addInterceptor(zipkinInterceptor);
        }
    }
    
  2. 在拦截器上加@Component注解

    @Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
    @Component
    public class UserAuthorityDataInterceptor implements Interceptor
    
资料参考

《MyBatis从入门到精通》——刘增辉(PageHelper作者)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值