内容

Interceptor接口与@Intercepts注解

org.apache.ibatis.plugin.Interceptor 是ibatis包的接口,

org.apache.ibatis.plugin.Intercepts 是ibatis包的注解

我们可以实现Interceptor 接口,并标注@Intercepts注解,

做一个mybatis执行SQL时的拦截器。

PageHelper实现拦截器

著名Mybatis插件Pagehelper就是这样实现了它的拦截器:

com.github.pagehelper.PageInterceptor

com.github.pagehelper.QueryInterceptor

@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}),
    }
)
public class QueryInterceptor implements Interceptor {
	...
}

默认数据源与拦截器

在这里插入图片描述
默认配置下,sqlSessionFactory自己添加了拦截器
在这里插入图片描述

自定义数据源与拦截器的问题

不过最近同事那出了一个问题,系统之前使用这个拦截器没问题,突然就不能用了。

通过排查Mybatis源码,调用到拦截器的栈如下:

在这里插入图片描述

可以看到,在org.apache.ibatis.plugin.Plugin的方法中,会调用拦截器实现类的的intercept方法

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  try {
    Set<Method> methods = signatureMap.get(method.getDeclaringClass());
    if (methods != null && methods.contains(method)) {
      return interceptor.intercept(new Invocation(target, method, args));
    }
    return method.invoke(target, args);
  } catch (Exception e) {
    throw ExceptionUtil.unwrapThrowable(e);
  }
}

那么走不到拦截器,说明没注入,

我们查看对应mapper对象,看sqlSessionFactory中有没有拦截器,路径如下:

((InterceptorChain)((Configuration)((DefaultSqlSessionFactory)((SqlSessionTemplate)((MapperProxy)this.h).sqlSession).sqlSessionFactory).configuration).interceptorChain).interceptors

发现自定义的数据源时没有的,如果是Spring默认数据源配置,会帮我们注入好,如下

在这里插入图片描述

自定义数据源注入拦截器

//1.在自定义配置类上@Import对应拦截器,供SpringBoot对其装配,其实不写这一步也能让拦截器生效,写了可以让下面注入的属性不报红,还没细看如何自动注入的拦截器,不过大概就是该注解所标注的类、该接口的实现类都进行了BeanDefinition的注册之类的
@Import({***Interceptor.class, ***Interceptor.class})

//注入拦截器
	@Autowired
    private ***Interceptor ***Interceptor;
    @Autowired
    private ***Interceptor ***Interceptor;


//3.在生成SqlSessionFactory的方法中,通过setPlugins设置拦截器
	@Bean
    @Primary
    public SqlSessionFactory sqlSessionFactoryFfhj() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(ffhjds);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/*.xml")
        );
        //重点
        factoryBean.setPlugins(new Interceptor[]{***Interceptor, ***Interceptor});
        return factoryBean.getObject();
    }

测试一遍,使用mapper时可以走到拦截器中了

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐