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直接向容器索要。
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐