项目运行一段时间,会报错:
java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
环境:
spring项目中用到了quartz定时器,其中定时任务job中用到了类似如下的代码:
String realService = ""; int isRedis = Integer.parseInt(PropertieUtil.getConfig("config.isRedis")); if (isRedis==1) { //切换为redis版本 realService = "xxxServiceImpl1"; }else { realService = "xxxServiceImpl2" } //本地查询文档表服务 XxxService xxxService = (XxxService) SpringContext.getApplicationContext().getBean(realService);
本意是想根据配置文件中的一个字段来决定加载哪个具体实现类,实现版本切换。
解决:
百度了一下,
找到如下文章:
-
错误原因:BeanFactory没有实例化或者已经关闭。原因很简单:ApplicationContext ctx = new ClassPathXmlApplicationContext();Spring实例化BeanFactory的时候是默认到classPath下面查找名为applicationContext.xml的文件。
这正是这个错误的原因,修改为:ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
如果这样的话就不会出现这样的错误了。
applicationContext.xml,,,,可以是自己命名的xml。。。
来自网络:http://blog.sina.com.cn/s/blog_80e498b10100w10b.html
-
你是不是写了获取xml的方式来创建服务,类似于下面的这种:
ApplicationContext ctx = new ClassPathXmlApplicationContext();
UserService service = (UserService)ctx.getBean("bean.xml");
=======================
自己思路:
想到可能是job里面是多线程,多线程中用SpringContext.getApplicationContext().getBean 临时加载多个类可能会有问题,所以,改为不在代码里判断使用哪个实现类,而是直接在项目启动时就将要使用的实现类直接配置的 spring的配置文件的 xml中的 bean 中。
运行一段时间发现,还是问题依旧,既然不是类初始化的问题,那么就是类获取的问题,代码中其实是在定时任务的多线程类(job实现类)中有如下的获取spring类的方式:
程序运行一段时间,39行就会报错。
想到多半还是由于quartz的多线程和spring加载类操作可能会有bug,又有思路:不在多线程中获取spring容器中的类,而是在外面把多线程方法中需要的service都获取到,然后通过传递参数的形式传递到多线程方法中,再使用,也就是代码改为:
也就是在创建job实现类时就把service作为参数传递到多线程方法中,然后在方法中从参数中获取,而不是在方法中从spring容器中获取,经过一段时间的验证,果然问题解决了。
参考:
参数放入时的部分代码: