基於@PostConstruct註解的使用,解決向靜態變量註入值
@PostConstruct註解的使用,向靜態變量註入值
今天在編寫工具類時遇到瞭一個問題,一般在定義工具類方時,我們會將工具類中的方法定義成static類型,使用時可以通過類名.方法名獲取該方法,無需實例化出對象才能使用其內部方法,但是當有些參數在配置文件中定義時,我們需要拿到這些參數就需要在工具類方法使用@Value註解進行參數註入,但是@Value並不支持向static變量進行註入(spring並不推薦將變量或對象聲明為static類型,因為這樣擴大瞭他們的使用范圍,spring依賴註入的目的就是,需要對象時進行向容器中註入,在整個聲明周期中使用到他們,同時也讓testing工作更加容易,一但聲明為static後,就不需要再產生該對象的實例,這會讓testing變得更加困難,同時你也不能為一個給定的類,依靠註入方式去產生多個具有不同的依賴環境的實例.
這種static field是隱含共享的,並且是一種global全局狀態,spring同樣不推薦這樣去做.)
因此現在工具類中的參數如何進行使用,現在註入的參數是非靜態的,而方法是靜態的,如何在靜態方法中使用到非靜態變量呢?
可以使用@PostConstruct註解進行使用
說說思路
我們可以通過非靜態變量進行註入值,再通過@PostConstruct定義的init方法進行將非靜態的變量值賦給靜態變量值(這裡需要瞭解下類加載的先後順序)
代碼如下:
@Component public class BaiduTranslateUtils { private static Logger logger = LoggerFactory.getLogger(BaiduTranslateUtils.class); private static String BAIDU_FROM = "en"; private static String BAIDU_TO = "zh"; private static String BAIDU_DST = "dst"; private static String APP_ID; private static String SECURITY_KEY; @Value("${baidu.translate.app_id}") private String app_id; @Value("${baidu.translate.security_key}") private String security_key; @PostConstruct public void init(){ //初始化賦值 APP_ID = app_id; SECURITY_KEY = security_key; } public static String getEntozhOfString(String dis){ //靜態方法使用靜態變量 System.out.println(APP_ID+SECURITY_KEY); } }
@PostConstruct和靜態變量註入和spring初始化
@PostConstruct這個註解是由Java提供的,而不是spring提供的,它用來修飾一個非靜態的void方法。它會在服務器加載Servlet的時候運行,並且隻運行一次。bean創建完成空對象,就開始進行@Autowire、@PostConstruct賦值。
@Component public class SystemConstant { public static String surroundings; @Value("${spring.profiles.active}") public String environment; @PostConstruct public void initialize() { System.out.println("初始化環境..."); surroundings = this.environment; } }
執行順序
- 第一種:當直接調用(沒有new對象)靜態方法時候:代碼塊(靜態變量按照順序)就執行—–方法執行。
- 第二種創建對象:執行父類靜態代碼—-執行子類的靜態代碼—-執行父類構造方法—–執行子類的構造方法(註:@PostConstruct修飾的方法是在構造方法之後執行的)
註:靜態變量和靜態代碼塊都是按照代碼書寫順序執行的,對於靜態代碼塊隻要是操作(調用靜態方法或者新建一個類等)這個類就會執行(包括靜態變量)
靜態變量也可以用value註解進行註入,隻要將註解放在變量的set方法上即可,且方法不可為靜態方法
@Component public class SystemConstant { public static String surroundings; @Value("${spring.profiles.active}") public String environment; @Value("${spring.profiles.active}") public void setSurroundings(String surroundings ){ SystemConstant .surroundings = surroundings; } }
關於spring初始化操作
實現ApplicationRunner接口,然後Override這個ApplicationRunner接口的run方法即可
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Springboot啟動執行特定代碼的方式匯總
- 使用Spring啟動時運行自定義業務
- springBoot啟動時讓方法自動執行的幾種實現方式
- Spring啟動時實現初始化有哪些方式?
- SpringBoot 在項目啟動之後執行自定義方法的兩種方式小結