一、背景
最近在使用工具类实现将数据库中的数据批量导入到Solr索引库的时候,使用单元测试提示:
java.lang.IllegalStateException: Failed to load ApplicationContext
在解决问题的过程中,偶然发现了Spring和SpringMVC是有父子容器关系的,正是由于这种父子容器关系的存在,导致了问题的存在。
二、错误重现
下面是我的测试类:
public class SolrUtil {
@Autowired
private GoodsDao goodsDao;
@Autowired
private SolrTemplate solrTemplate;
//实现将数据库中的数据批量导入到Solr索引库中
@Test
public void importGoodsData() {
List<Goods> list = goodsDao.findAll();
System.out.println("===数据库中的数据===");
for(Goods goods : list) {
System.out.println(goods.getId()+" "+goods.getTitle());
}
solrTemplate.saveBeans(list);
solrTemplate.commit();
System.out.println("===结束===");
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/*.xml");
// context = new ClassPathXmlApplicationContext("classpath:spring/*.xml");
SolrUtil solrUtil = (SolrUtil) context.getBean("solrUtil");
solrUtil.importGoodsData();
}
}
?
我开始没有使用junit进行单元测试,直接执行的main方法。注意我加载的配置文件,先看下我的目录结构:
?
?
可以看出我把SpringMVC的配置文件也加载进来了。一开始我以为是jar包冲突,换了jar包的版本,后来发现tomcat启动正常,执行其他对数据库的操作也没有问题,我就排除了这方面的问题。然后我突然想到可以用junit进行单元测试,于是有了下面的代码
?
@Component
@ContextConfiguration(locations="classpath:spring/*.xml")
@RunWith(SpringJUnit4Cla***unner.class)
可以看到我使用了@ContextConfiguration注解,这个注解的作用是啥呢?
@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件
这时候我就考虑到了是不是通配符写错的原因呢?于是有了下面这行代码
@ContextConfiguration(locations= {"classpath:spring/spring-solr.xml","classpath:spring/spring-service.xml","classpath:spring/spring-dao.xml","classpath:spring/spring-shiro.xml",})
碰巧我没有加载SpringMVC的配置文件,于是问题就解决了。
三、原因分析
?在Spring整体框架的核心概念中,容器是核心思想,就是用来管理Bean的整个生命周期的。Spring和SpringMVC的容器存在父子关系,即Spring是父容器,SpringMVC是其子容器,子容器可以访问父容器的对象,父容器不能访问子容器的类。另外Spring会把使用了@Component注解的类,并且将它们自动注册到容器中。这也是我们为什么不在Spring容器管理controller的原因,即:一定要把不同的bean放到不同的容器中管理。
?
四、后记
?
折腾了一天,终于解决了这个问题,特此记录一下,-_- 。
原文地址:http://blog.51cto.com/13416247/2309590