1. 程式人生 > 其它 >thymeleaf中js無法解析陣列的問題

thymeleaf中js無法解析陣列的問題

技術標籤:spring依賴注入java

Spring 能否依賴注入 static 靜態變數

今天在使用springboot寫專案時,在service進行值域校驗,由於反覆用到一段程式碼,所以想將其封裝為常用工具方法。程式碼如下:

 // 就診類別值域驗證
        String visittypeRange = checkRangeMapper.checkRange(RangeConstant.VISITTYPECODE);
        JSONObject visittypeJsonObject = JSON.parseObject(visittypeRange);
        Object visittypeObj =
visittypeJsonObject.get(drugTestReportDetailDTO.getVisittype()); if (visittypeObj == null) { throw new ConsulationException("visittype值域範圍錯誤"); } // 驗證性別 String sexRange = checkRangeMapper.checkRange(RangeConstant.SEXCODE); JSONObject jsonObject =
JSON.parseObject(sexRange); Object o = jsonObject.get(drugTestReportDetailDTO.getSex()); if (o == null) { throw new ConsulationException("sex值域範圍錯誤"); }

由於程式碼中涉及到了mapper物件,需要在工具類中注入。
工具類中一般為靜態方法,如果要呼叫類中的屬性,必須為靜態屬性,但是我們知道spring針對的是物件的管理。

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

在這裡插入圖片描述

@Autowired
private static YourClass yourClass;
可以試一下, yourClass 在這種狀態下不能夠被依賴注入, 會丟擲執行時異常 java.lang.NullPointerException, 為什麼呢? 靜態變數 / 類變數不是物件的屬性, 而是一個類的屬性, spring 則是基於物件層面上的依賴注入.
而使用靜態變數 / 類變數擴大了靜態方法的使用範圍. 靜態方法在 spring 是不推薦使用的. 依賴注入的主要目的, 是讓容器去產生一個物件的例項, 然後在整個生命週期中使用他們, 同時也讓 testing 工作更加容易.
一旦你使用靜態方法, 就不再需要去產生這個類的例項, 這會讓 testing 變得更加困難, 同時你也不能為一個給定的類, 依靠注入方式去產生多個具有不同的依賴環境的例項. 這種 static field 是隱含共享的, 並且是一種 global 全域性狀態, spring 同樣不推薦這樣去做.

3.Spring 靜態注入的三種方式
Spring 靜態注入的三種方式:
(說明:MongoFileOperationUtil 是自己封裝的一個 Mongodb 檔案讀寫工具類,裡面需要依賴 AdvancedDatastore 物件例項,dsForRW 用來獲取 Mongodb 資料來源)
在 springframework 裡,我們不能 @Autowired 一個靜態變數, 使之成為一個 spring bean,例如下面這種方式:

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

public class MongoFileOperationUtil {
private static AdvancedDatastore dsForRW;  

private static MongoFileOperationUtil mongoFileOperationUtil;  

public void init() {  
    mongoFileOperationUtil = this;  
    mongoFileOperationUtil.dsForRW = this.dsForRW;  
}  

}
這種方式適合基於 XML 配置的 WEB 專案;
[email protected] 方式實現;

import org.mongodb.morphia.AdvancedDatastore;
import org.springframework.beans.factory.annotation.Autowired;

@Component
public class MongoFileOperationUtil {
@Autowired
private static AdvancedDatastore dsForRW;

private static MongoFileOperationUtil mongoFileOperationUtil;  

@PostConstruct  
public void init() {  
    mongoFileOperationUtil = this;  
    mongoFileOperationUtil.dsForRW = this.dsForRW;  
}  

}
@PostConstruct 註解的方法在載入類的建構函式之後執行,也就是在載入了建構函式之後,執行 init 方法;(@PreDestroy 註解定義容器銷燬之前的所做的操作)
這種方式和在 xml 中配置 init-method 和 destory-method 方法差不多,定義 spring 容器在初始化 bean 和容器銷燬之前的所做的操作;
3.set 方法上新增 @Autowired 註解,類定義上新增 @Component 註解;

import org.mongodb.morphia.AdvancedDatastore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MongoFileOperationUtil {

private static AdvancedDatastore dsForRW;  
  
@Autowired  
public void setDatastore(AdvancedDatastore dsForRW) {  
    MongoFileOperationUtil.dsForRW = dsForRW;  
}  

}
首先 Spring 要能掃描到 AdvancedDatastore 的 bean,然後通過 setter 方法注入;
然後注意:成員變數上不需要再新增 @Autowired 註解;

本文借鑑自:(https://www.cnblogs.com/jiading/articles/12488077.html)