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 方式實現:
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)