1. 程式人生 > >Spring靜態注入的三種方式

Spring靜態注入的三種方式

Spring靜態注入的三種方式:

(說明:MongoFileOperationUtil是自己封裝的一個Mongodb檔案讀寫工具類,裡面需要依賴AdvancedDatastore物件例項,dsForRW用來獲取Mongodb資料來源)

在springframework裡,我們不能@Autowired一個靜態變數,使之成為一個spring bean,例如下面這種方式:

[java]  view plain  copy
  1. @Autowired  
  2. private static AdvancedDatastore dsForRW;  
可以試一下, dsForRW 在這種狀態下不能夠被依賴注入,會丟擲執行時異常java.lang.NullPointerException,為什麼呢?靜態變數/類變數不是物件的屬性,而是一個類的屬性,spring則是基於物件層面上的依賴注入。
但是自己比較喜歡封裝工具類,並通過@Component註解成功能元件,但是功能元件中的方法一般都是靜態方法,靜態方法只能呼叫靜態成員變數,於是就有了下面的問題。封有的時候封裝功能元件會需要底層的service注入,怎麼辦呢?

去網上搜了下解決辦法,簡單總結一下幾種實現方式;

1.xml方式實現;

[html]  view plain  copy
  1. <bean id="mongoFileOperationUtil" class="com.*.*.MongoFileOperationUtil" init-method="init">  
  2.     <property 
    name="dsForRW" ref="dsForRW"/>  
  3. </bean>  

[java]  view plain  copy
  1. public class MongoFileOperationUtil {  
  2.       
  3.     private static AdvancedDatastore dsForRW;  
  4.   
  5.     private static MongoFileOperationUtil mongoFileOperationUtil;  
  6.   
  7.     public void init() {  
  8.         mongoFileOperationUtil = this;  
  9.         mongoFileOperationUtil.dsForRW = this.dsForRW;  
  10.     }  
  11.   
  12. }  
這種方式適合基於XML配置的WEB專案;


[email protected]方式實現;

[java]  view plain  copy
  1. import org.mongodb.morphia.AdvancedDatastore;  
  2. import org.springframework.beans.factory.annotation.Autowired;  
  3.   
  4.   
  5. @Component  
  6. public class MongoFileOperationUtil {  
  7.     @Autowired  
  8.     private static AdvancedDatastore dsForRW;  
  9.   
  10.     private static MongoFileOperationUtil mongoFileOperationUtil;  
  11.   
  12.     @PostConstruct  
  13.     public void init() {  
  14.         mongoFileOperationUtil = this;  
  15.         mongoFileOperationUtil.dsForRW = this.dsForRW;  
  16.     }  
  17.   
  18. }  
@PostConstruct 註解的方法在載入類的建構函式之後執行,也就是在載入了建構函式之後,執行init方法;(@PreDestroy 註解定義容器銷燬之前的所做的操作)

這種方式和在xml中配置 init-method和 destory-method方法差不多,定義spring 容器在初始化bean 和容器銷燬之前的所做的操作;


3.set方法上新增@Autowired註解,類定義上新增@Component註解;

[java]  view plain  copy
  1. import org.mongodb.morphia.AdvancedDatastore;  
  2. import org.springframework.beans.factory.annotation.Autowired;  
  3. import org.springframework.stereotype.Component;  
  4.   
  5.   
  6. @Component  
  7. public class MongoFileOperationUtil {  
  8.   
  9.     private static AdvancedDatastore dsForRW;  
  10.       
  11.     @Autowired  
  12.     public void setDatastore(AdvancedDatastore dsForRW) {  
  13.         MongoFileOperationUtil.dsForRW = dsForRW;  
  14.     }  
  15. }  

首先Spring要能掃描到AdvancedDatastore的bean,然後通過setter方法注入;

然後注意:成員變數上不需要再新增@Autowired註解;

以上為轉載

前面兩種沒試過,用了第三種方法,需要注意的是:

1、雖然你添加了@Component 這個標籤在工具類上,但是你必須保證spring在載入配置檔案的時(application-*.xml),其中要有配置檔案開啟了你工具類所在的包的註解,也就是說,你工具類和其他controller、service類可能不放在同一個包下,先前在配置那兩種類掃描註解的時候配的可能只是那兩種類相應所在的包的路徑,那工具類的@Component註解就掃描不到了,那樣工具類需要注入的靜態變數就會注入失敗,所以可以新建一個application-utils.xml來配置工具類的掃描註解。或者直接在spring載入的某個application-*.xml檔案中配置一個bean,class屬性指向你的工具類,如 <bean class="com.hy.utils.JedisUtils"></bean>,這樣工具類上的@Component註解也可以不需要了。兩個途徑的目的就是要讓spring管理到你的工具類。

2、如果你需要注入的靜態變數是spring未知的類(非基本資料型別和string、以及非註解過的類(@Component、@controller、@service、@repository)),也需要讓spring管理到,就是要在spring載入的某個application-*.xml檔案中配置bean。

3、還需要注意的是,靜態變數的setter方法的static關鍵字要去掉,不然會注入失敗。

綜上,前兩種方法應該也需要注意是否被spring管理的問題

更新

有些屬性可能不支援@Autowired,改用@Resource(name="?"),如

org. springframework. data. redis. core.RedisTemplate< StringObject>