java 靜態代碼塊和spring @value等註解注入順序
問題所在
先上代碼
java方法
@Value("${mf.cashost}") public static String casHost; public static String getCasHost() { if (StringUtils.isEmpty(casHost)) { //casHost = "http://sso.abc.com.cn/sso/"; casHost = "http://ssotest.abc.com.cn/sso/"; } return casHost; }
配置文件
mf.cashost=http://sso.abc.com.cn/sso/
正常咱們想要的getCasHost
的值,確定是sso.abc.com.cn
,而不是ssotest
,可是若是調用getCasHost
確定是返回test
的,或者說,casHost最開始進到getCasHost的方法時,就是空的。java
分析一波
關於實例變量與構造方法的初始化順序問題spring
- Java類會先執行構造方法,而後再給註解了@Value 的屬性注入值,因此在執行靜態代碼塊的時候,就會爲null。
- Java 及Spring 初始化順序:java靜態屬性/靜態代碼塊(根據聲明的前後順序加載)、構造代碼塊、 構造方法(即:spring建立FetchStockSchedule的實例 交給Spring 管理)、@Value/@ AutoWired/@Resouce 等註解 的成員變量等賦值。
解決一下
解決方案
- 首先,讓當前類變成Spring的bean,
- 再使用@PostConstruct
@Value("${mf.cashost}") private String mfCasHost; private static String casHost; @PostConstruct public void init() { casHost = mfCasHost; } public static String getCasHost() { if (StringUtils.isEmpty(casHost)) { casHost = "http://ssotest.abc.com.cn/sso/"; } return casHost; }
原理
Java中該註解的說明:
@PostConstruct
該註解被用來修飾一個非靜態的void()
方法。被@PostConstruct
修飾的方法會在服務器加載Servlet
的時候運行,而且只會被服務器執行一次。PostConstruct在構造函數以後執行,init()方法以前執行。服務器
一般咱們會是在Spring框架中使用到@PostConstruct註解 該註解的方法在整個Bean初始化中的執行順序:
此時的執行順序:框架
- 構造方法
- Before Initialization
- 使用PostConstruct註解
- InitializingBean接口
- init-method指定的初始化方法
- After Initialization