項目運行一段時間,會報錯:html
java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContextjava
環境:redis
spring項目中用到了quartz定時器,其中定時任務job中用到了相似以下的代碼:spring
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);
本意是想根據配置文件中的一個字段來決定加載哪一個具體實現類,實現版本切換。tomcat
解決:網絡
百度了一下,多線程
找到以下文章:app
-
錯誤緣由: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");
=======================maven
本身思路:post
想到多是job裏面是多線程,多線程中用SpringContext.getApplicationContext().getBean 臨時加載多個類可能會有問題,因此,改成不在代碼裏判斷使用哪一個實現類,而是直接在項目啓動時就將要使用的實現類直接配置的 spring的配置文件的 xml中的 bean 中。
運行一段時間發現,仍是問題依舊,既然不是類初始化的問題,那麼就是類獲取的問題,代碼中實際上是在定時任務的多線程類(job實現類)中有以下的獲取spring類的方式:
程序運行一段時間,39行就會報錯。
想到多半仍是因爲quartz的多線程和spring加載類操做可能會有bug,又有思路:不在多線程中獲取spring容器中的類,而是在外面把多線程方法中須要的service都獲取到,而後經過傳遞參數的形式傳遞到多線程方法中,再使用,也就是代碼改成:
也就是在建立job實現類時就把service做爲參數傳遞到多線程方法中,而後在方法中從參數中獲取,而不是在方法中從spring容器中獲取,通過一段時間的驗證,果真問題解決了。
參考:
參數放入時的部分代碼: