Mybatis启动递归层次太多导致Stackoverflow
前段时间有一次启动Spring+Mybatis项目,遇到了线程栈内存溢出的情况。好在虚拟机在崩溃的时候将线程栈中的方法调用关系都打印了出来,问题也非常好定位。
经过debug发现,为Dao生成代理的时候首先要生成它的FactoryBean,也就是MapperFactoryBean。而MapperFactoryBean继承了 SqlSessionDaoSupport。其中,SqlSessionDaoSupport有两个声明了Autowired的方法:
@Autowired(required = false)
public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
@Autowired(required = false)
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSession = sqlSessionTemplate;
this.externalSqlSession = true;
}
当 MapperFactoryBean实例生成之后,Spring给它注入SqlSessionTemplate。而注入SqlSessionTemplate的过程中会向容器获取所有的Dao,对于已经在容器中的Dao所对应的bean可以直接获取返回,若还没有创建bean,则Spring又会先创建这个Dao的MapperFactoryBean。创建MapperFactoryBean的时候会再次注入SqlSessionTemplate。就这样一直循环下去,直到所有的Dao都已经创建完毕,这个过程才算结束。
引起问题的原因已经找出来了,接下来就得想办法解决掉问题。要么是自己的使用方式不对,要么就是框架的问题。出现上面问题的罪魁祸首就是mybatis-spring的版本太低了,在新版中这个问题已经得到了解决。项目中引用的maven如下:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.1.1</version>
</dependency>
只需要将版本升级到1.2.3即可,项目中spring的版本为3.0.5,没有尝试其他版本。在新版下,上面两个方法的Autowired的标注已经去掉,取而代之的注入方式是利用id直接向容器索要。