引言
在对数据库进行新增记录的JUnit测试时,抛出一个BeanCreationNotAllowedException异常:
异常分析与解决
异常信息太长,图片截不下,粘贴来看:
Exception in thread "pool-2-thread-1" org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'redisConnectionFactory': Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
异常代码:
@Testpublic void testAddOrUpdateUser() throws InterruptedException {JSONObject teacher = new JSONObject();teacher.put("role", "teacher");teacher.put("teacherName", "王力宏");teacher.put("jobTitle", "助理教授");teacher.put("gender", "男");teacher.put("username", "wanglihong");SystemResult addOrUpdateUser = userService.addOrUpdateUser(teacher);System.out.println(addOrUpdateUser);}
测试方法的关键调用函数是:userService.addOrUpdateUser(teacher); 可是在这个方法内部完全没有用到redis的相关内容,而且奇怪的是:用debug模式运行方法的话完全可以成功。
莫名其妙!
来看一下addOrUpdateUser方法:
@Override@SuppressWarnings("rawtypes")public SystemResult addOrUpdateUser(Object user) {Boolean isTeacher = checkSvc.checkTeacherByRole(user);boolean isStudent = !isTeacher;String userStr = null;Class clazz = null;if (isTeacher) {// 添加教师Teacher teacher = JSONObject.toJavaObject(JSONObject.parseObject(JSONObject.toJSONString(user)),Teacher.class);DBProcessor.execute(() -> {tchrRep.save(teacher);});// ......} else if (isStudent) {// ......}logger.info("添加或更新<" + clazz.getSimpleName() + "> : " + userStr);String resultMessage = "添加或更新" + (isTeacher ? "教师" : "学生") + "成功!";return new SystemResult(SysContents.SUCCESS, resultMessage, clazz.getSimpleName().toLowerCase());}
我已经简化了部分代码,关键就是执行save方法的前后,可以看出此处的save方法,我为了充分利用并发性,采用了多线程的方式,将保存任务交给了一个ExecutorService——DBProcessor去执行。
交给一个新的线程去执行就是问题所在!
其实,细致分析一下就可以发现,我们采用debug的方式,或者将任务不交给线程去执行,而是串行直接执行任务,就不会有问题,原因就是,分配新的线程执行任务需要一定的性能和时间开销,因此会稍微比JUnit测试方法延迟一些。这样当JUnit方法执行完成立刻退出之后,整个系统环境也就直接退出关闭,没有给新的线程足够的时间去执行任务,因此才会导致插入失败。
顺着这个思路,我在JUnit方法执行到addOrUpdateUser之后sleep 1秒钟,果然顺利通过测试。
至于异常所描述的创建bean失败,我想就是因为JUnit测试结束之后过早退出系统环境的原因。
另外,这个问题网上的出错原因也并不一致,还要根据自己的问题具体分析。
如有疑问,欢迎留言。