SpringBoot整合Mybatis自定义拦截器不起作用的处理方案

网友投稿 269 2022-12-06

SpringBoot整合Mybatis自定义拦截器不起作用的处理方案

目录SpringBoot整合Mybatis自定义拦截器不起作用1. 原始的读取mybatis-config.xml文件2. 与SpringBoot容器整合2.1 mybatis的自动装载3. 在mybatis-config.xml配置又放入Spring容器SpringBoot 自定义Mybatis拦截器第一种第二种第三种

SpringBoot整合Mybatis自定义拦截器不起作用

Mybatis插件生效的方式:

1. 原始的读取mybatis-config.xml文件

该方式和Spring无关,是通过反射的形式创建插件对象,此时会执行org.apache.ibatis.plugin.Interceptor#setProperties方法,以读取配置参数。

mybatis:

mapper-locations: classpath*:/mapping/*.xml

type-aliases-package: com.tellme.pojo

#读取全局配置的地址

config-location: classpath:mybatis-config.xml

在resource目录下配置mybatis的全局配置:

2. 与SpringBoot容器整合

网上很多方案说:mybatis自定义拦截器上加上@Component注解便可以生效。但是我将自定义拦截器放入到Spring容器中,自定义拦截器却失效了。

然后找到了springboot配置多数据源后mybatis拦截器失效文章,说是自定义配置了数据源导致了拦截器失效。

2.1 mybatis的自动装载

源码位置:org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

@Configuration

@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })

@ConditionalOnBean(DataSource.class)

@EnableConfigurationProperties(MybatisProperties.class)

@AutoConfigureAfter(DataSourceAutoConfiguration.class)

public class MybatisAutoConfiguration {

private static Log log = LogFactory.getLog(MybatisAutoConfiguration.class);

@Autowired

private MybatisProperties properties;

//会依赖注入Spring容器中所有的mybatis的Interceptor拦截器

@Autowired(required = false)

private Interceptor[] interceptors;

...

@Bean

@ConditionalOnMissingBean

public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {

SqlSessionFactoryBean factory = new SqlSessionFactoryBean();

factory.setDataSource(dataSource);

factory.setVfs(SpringBootVFS.class);

if (StringUtils.hasText(this.properties.getConfigLocation())) {

factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));

}

factory.setConfiguration(properties.getConfiguration());

//手动放入到了setPlugins方法中。

if (!ObjectUtils.isEmpty(this.interceptors)) {

factory.setPlugins(this.interceptors);

}

if (this.databaseIdProvider != null) {

factory.setDatabaseIdProvider(this.databaseIdProvider);

}

if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {

factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());

}

if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {

factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());

}

if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {

factory.setMapperLocations(this.properties.resolveMapperLocations());

}

return factory.getObject();

}

...

}

上面源码中:自动注入了Interceptor[]数组(我们只需将mybatis的自定义拦截器对象放入到Spring容器中)。后续放入了sqlSessionFactory中。

但是项目中虽然自定义配置了sqlSessionFactory类,但却未设置factory.setPlugins(this.interceptors);。导致即使将自定义拦截器放入到Spring容器,但却不生效。

解决方法,需要手动修改自定义的sqlSessionFactory类。

3. 在mybatis-config.xml配置又放入Spring容器

这种情况下,mybatis自定义拦截器会被执行两次。即在mybatis-config.xml配置的拦截器会通过反射的方式创建拦截器,放入Spring容器的拦截器也会被初始化。

源码位置:org.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory

protected SqlSessionFactory buildSqlSessionFactory() throws IOException {

Configuration configuration;

...读取属性中的plugins,即org.mybatis.spring.SqlSessionFactoryBean#setPlugins设置的。

if (!isEmpty(this.plugins)) {

for (Interceptor plugin: this.plugins) {

configuration.addInterceptor(plugin);

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Registered plugin: '" + plugin + "'");

}

}

}

...解析xml配置(通过反射创建拦截器对象)

if (xmlConfigBuilder != null) {

try {

xmlConfigBuilder.parse();

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'");

}

} catch(Exception ex) {

throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);

} finally {

ErrorContext.instance().reset();

}

}

return this.sqlSessionFactoryBuilder.build(configuration);

}

最终会执行到:

private void pluginElement(XNode parent) throws Exception {

if (parent != null) {

for (XNode child: parent.getChildren()) {

String interceptor = child.getStringAttribute("interceptor");

Properties properties = child.getChildrenAsProperties();

//反射创建mybatis的插件。

Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();

interceptorInstance.setProperties(properties);

configuration.addInterceptor(interceptorInstance);

}

}

}

SpringBoot 自定义Mybatis拦截器

开发过程中经常回需要对要执行的sql加以自定义处理,比如分页,计数等。通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名http://即可。

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

public class MyPageInterceptor implements Interceptor {

private static final Logger logger= LoggerFactory.getLogger(MyPageInterceptor.class);

@Override

public Object intercept(Invocation invocation) throws Throwable {

logger.warn(invocation.toString());

return invocation.proceed();

}

@Override

public Object plugin(Object o) {

return Plugin.wrap(o,this);

}

@Override

public void setProperties(Properties properties) {

logger.warn(properties.toString());

}

}

我的配置

mybatis:

type-aliases-package: me.zingon.pagehelper.model

mapper-locations: classpath:mapper/*.xml

configuration:

map-underscore-to-camel-case: true

default-fetch-size: 100

default-statement-timeout: 30

在springboot中要给mybatis加上这个拦截器,有三种方法,前两种方法在启动项目时不会自动调用自定义拦截器的setProperties方法。

第一种

直接给自定义拦截器添加一个@Component注解,当调用sql时结果如下,可以看到拦截器生效了,但是启动时候并没有自动调用setProperties方法。

第二种

在配置类里添加拦截器,这种方法结果同上,也不会自动调用setProperties方法。

@Configuration

public class MybatisConfig {

@Bean

ConfigurationCustomizer mybatisConfigurationCustomizer() {

return new ConfigurationCustomizer() {

@Override

public void customize(org.apache.ibatis.session.Configuration configuration) {

configuration.addInterceptor(new MyPageInterceptor());

}

};

}

}

第三种

这种方法就是跟以前的配置方法类似,在yml配置文件中指定mybatis的xml配置文件,注意config-location属性和configuration属性不能同时指定

mybatis:

config-location: classpath:mybatis.xml

type-aliases-package: me.zingon.pagehelper.model

mapper-locations: classpath:mapper/*.xml

"http://mybatis.org/dtd/mybatis-3-config.dtd">

可以看到,在启动项目的时候setProperties被自动调用了

前两种方法可以在初始化自定义拦截器的时候通过 @Value 注解直接初始化需要的参数。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详解Spring配置及事务的使用
下一篇:springboot配置多数据源后mybatis拦截器失效的解决
相关文章

 发表评论

暂时没有评论,来抢沙发吧~