程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 線程中無法實例化spring注入的服務的解決辦法,實例spring

線程中無法實例化spring注入的服務的解決辦法,實例spring

編輯:JAVA綜合教程

線程中無法實例化spring注入的服務的解決辦法,實例spring


  問題描述

  在Java Web應用中采用多線程處理數據,發現Spring注入的服務一直報NullPointerException。使用注解式的聲明@Resource和XML配置的bean聲明,都報空指針。然後尋找萬能的網絡尋找幫助,有的說spring因為考慮到線程安全問題,不支持注入,以及spring的bean聲明周期,在工程啟動時,沒有檢測到線程中的bean,進行注入。看來只能主動去獲取spring聲明的周期。

 

  解決辦法:

  (1)主動實例化對象(不推薦)

 private TestService testService = new TestServiceImpl();

    每次加載這個類,就會重新創建一次,會過多耗費資源。

  (2)把線程設置為主程序的內部類,或者是利用線程的構造方法把bean傳遞過去

    主程序在web容器加載時,肯定是可以注入Spring bean的,那麼將線程的實現類放在主程序的類中便可以“共享”Spring的bean,將生成線程的線程池定義在主程序的類中,每個線程的實現類作為內部類也定義在主程序中。

 

 1 public class Test implements InitializingBean{
 2  
 3     @Resource
 4     private TestService testService
 5  
 6     public void close(){
 7     }
 8 
 9     public void afterPropertiesSet() throws Exception {
10         // 利用構造方法把bean傳遞過去
11         new Thread(testService);
12     }
13 }

 

 

 

  (3)用靜態方法直接取的容器中的spring對象

    寫一個SpringContextUtil類,實現ApplicationContextAware

 1 package com.test.utils;
 2 
 3 import java.util.Locale;
 4 import java.util.Map;
 5 
 6 import org.springframework.beans.BeansException;
 7 import org.springframework.context.ApplicationContext;
 8 import org.springframework.context.ApplicationContextAware;
 9 
10 public class SpringContextUtil implements ApplicationContextAware {
11 
12   private static ApplicationContext applicationContext = null;
13 
14 
15   public void setApplicationContext(ApplicationContext context) throws BeansException {
16     applicationContext = context;
17   }
18 
19 
20   /**
21    * 獲取applicationContext對象
22    * @return
23    */
24   public static ApplicationContext getApplicationContext() {
25     return applicationContext;
26   }
27 
28 
29   /**
30    * 根據bean的id來查找對象
31    * @param id
32    * @return
33    */
34 
35   public static <T> T getBeanById(String id) {
36     return (T) applicationContext.getBean(id);
37   }
38 
39 
40   /**
41    * 根據bean的class來查找對象
42    * @param c
43    * @return
44    */
45   public static <T> T getBeanByClass(Class c) {
46     return (T) applicationContext.getBean(c);
47   }
48 
49 
50   /**
51    * 根據bean的class來查找所有的對象(包括子類)
52    * @param c
53    * @return
54    */
55   public static Map getBeansByClass(Class c) {
56     return applicationContext.getBeansOfType(c);
57   }
58 
59   public static String getMessage(String key) {
60     return applicationContext.getMessage(key, null, Locale.getDefault());
61   }
62 
63 }

      在applicationContext.xml中聲明SpringContextUtil的bean

<bean id="springContextUtil" class="com.test.utils.SpringContextUtil"/>

      在線程中或線程調用的其他服務中可以主動加載bean,然後可以直接使用(testService必須是spring中配置的bean)

1 public void run() {
2   TestService testService = (TestService ) SpringContextUtil.getBean("testService");
3   testService.queryData(); 
4 }

       (4)看到網上說還可以通過BeanFactory來加載bean,沒有去實現過,上個代碼做個參考

 1 public class SpringBeanFactoryUtils implements BeanFactoryAware {  
 2   
 3     private static BeanFactory beanFactory = null;  
 4     private static SpringBeanFactoryUtils factoryUtils = null;  
 5       
 6    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {  
 7         SpringBeanFactoryUtils.beanFactory = beanFactory;  
 8     }  
 9     public static BeanFactory getBeanFactory() {  
10         return beanFactory;  
11     }  
12     public static SpringBeanFactoryUtils getInstance(){  
13         if(factoryUtils==null){  
14             //factoryUtils = (SpringBeanFactoryUtils)beanFactory.getBean("springBeanFactoryUtils");  
15             factoryUtils = new SpringBeanFactoryUtils();  
16         }  
17         return factoryUtils;  
18     }  
19     public static Object getBean(String name){  
20         return beanFactory.getBean(name);  
21     }  
22 }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved