公司要整合rabbitmq与mybatis拦截器做一个数据同步功能。

整合过程中大部分环节都没什么问题,就是遇到了mybatis拦截器

@Intercepts(@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}))
@Component
public class MyBatisInterceptor implements Interceptor

无法通过注解进行注入一些持久层的dao对象,导致dao一直取到空值。

取dao对象目的是要查询当前代码的执行环境是生产还是测试环境。

因为生产者代码不需要在测试环境执行,这个区分的数据存在数据库里面。

最初,我通过 @Autowired 是行不通的,因为

(截取自 https://segmentfault.com/a/1190000023915286 )

所以我继续寻找方法,于是我找到了用 ApplicationContext 的方式获取 spring容器 企图剑走偏锋

结果发现每一次执行 ClassPathXmlApplicationContext 都会导致容器重新加载,但是我这个 MyBatisInterceptor 带了 @Component 也会跟着重新加载,导致 isGrey 清空

甚至导致 RabbitmqConfig这个类 也跟着重新加载

导致这个监听容易一直重新加载,断点一直进入,这里有用到 messageListener 这个消息***也是一个 单例bean对象 ,也会重新加载

所以会导致测试的时候出现bug,因为这个系统环境信息 sysEnvInfo 只需要加载一次

所以 ApplicationContext 这个方式也是走不通,我不推荐。

思来想去,我发现mybatis拦截器具体实现逻辑的方法produceSqlData里面我用的是SpringBeanUtils.getBean方法就能获取得到数据,

RabbitTemplate 是定义在 RabbitmqConfig 代码里的, RabbitmqConfig 这个类是个 @Configuration 注解

@Configuration
public class RabbitmqConfig

但是获取的数据是通过 @Bean 方式获取的, SpringBeanUtils.getBean 无法获取到 sqlSessionFactory

这里面的dao对象,所以直接

SysEnvInfoDao sysEnvInfoDao = (SysEnvInfoDao)SpringBeanUtils.getBean("sysEnvInfoDao", SysEnvInfoDao.class);

也会报错,提示 sysEnvInfoDao没有被定义 。

所以我思索了下,在 @Configuration 可以 @Autowired 成功,那我为何不参考 rabbitTemplate 一样把 sysEnvInfo 也变成一个 bean的单例对象 呢?

于是我将 SysEnvInfo 如 rabbitTemplate 一样配置成了 单例bean对象,通过@Bean注解

在 MyBatisInterceptor 里面通过 SpringBeanUtils.getBean 方式获取,最后实践可行,不会出现重复加载容器的问题,也能在拦截器中取到 spring bean

原文链接:https://www.cnblogs.com/longLifeFrog/p/15862067.html