哈囉大家好,我是古古
在前幾篇文章中,我們有介紹了創建 Bean 的方法 @Component
、注入 Bean 的方法 @Autowired
、以及指定 Bean 名字的方法 @Qualifier
,所以到目前為止,我們可以說是對 Bean 已經有了更多的認識,現在的我們已經可以成功的在 Spring Boot 程式中運用 Bean 了!
那麼這篇文章,我們就會深入介紹一下,要如何在創建一個 Bean 出來之後,去初始化這個 Bean 的值
所謂的「Bean 的初始化」,指的是**「在 Bean 被創建出來之後,對這個 Bean 去做一些初始值的設定」**,譬如說把變數的值設定成 5,或是進行一些運算之類的,簡單的說就是對這個 Bean 去做初始的出廠設定就對了
舉個例子來說的話,我們可以來試著改寫一下之前所寫的 HpPrinter class,我們在這個 HpPrinter 裡面去加上一個 count 變數,去計算這台印表機還可以印幾次,所以每當我們 call 一次 print()
方法,這個 count 的數量就要減一,實際程式如下:
@Component
public class HpPrinter implements Printer {
private int count;
@Override
public void print(String message) {
count--;
System.out.println("HP 印表機: " + message);
System.out.println("剩餘使用次數: " + count);
}
}
而因為我們有在這個 HpPrinter 上面,去加上一個 @Component
,所以 Spring Boot 到時候就會為我們創建一個 hpPrinter 的 Bean 出來,並且存放在 Spring 容器裡面
不過到目前為止,因為我們沒有去設定 Bean 的初始化,因此 Spring Boot 就只會去把這個 Bean 給創建出來,並不會去為裡面的 count 值進行初始化,因此這個 hpPrinter Bean 裡面的 count 值就會是 0
如果我們想要讓 Spring Boot 在創建這個 hpPrinter 出來之後,同時也去為這個 count 變數賦予一個初始值,那麼我們就可以使用 @PostConstruct
來幫助我們達成這件事!
@PostConstruct
的用途,就是 「為這個 Bean 去進行初始化」,因此我們就可以透過 @PostConstruct
的功能,去設定這個 Bean 中的變數的初始值了
還是上面那個 HpPrinter 的例子,如果我們想要把 HpPrinter 裡面的 count 變數的值,去初始化成 5 的話,那麼我們就可以這樣做:
我們可以在 HpPrinter 這個 class 裡面,去新增一個新的方法,並且在這個方法上面加上 @PostConstruct
,這樣就可以在這個 「有加上 @PostConstruct
的方法中」,去初始化 Bean 的值了
像是我們在 HpPrinter 裡面,就去新增了一個 initialize()
的方法,並且在這個方法上面,去加上了 @PostConstruct
這行程式,因此我們就可以在這個 initialize()
的方法中,去初始化這個 Bean 的值,譬如說我們可以把 count 的值設成 5 之類的
所以到時候,當 Spring Boot 創建完 Bean 時,Spring Boot 就會接著去執行 「有加上 @PostConstruct
的那個方法」(此處指的就是 initialize()
方法),進而去完成 Bean 的初始化!
因此在這個情境下,Spring Boot 就是會去執行 initialize()
方法去進行初始化,將 count 的值設定成 5,所以到時候儲存在 Spring 容器裡面的 hpPrinter Bean,他裡面的 count 變數的值就會是 5
在前面有提到,我們是可以在 class 中新增一個方法,然後在該方法上加上 @PostConstruct
,這樣就可以在「該方法裡面」,去寫上初始化 Bean 的程式
不過這個「被加上 @PostConstruct
的方法」,他在宣告上也是有一些格式需要遵守的:
public
void
所以綜合以上 4 點的話,基本上這個「初始化 Bean 的方法」,通常就會長得像是下面這個樣子
public void XXX();
其中 XXX 可以替換成大家喜歡的單字,常見的有 setup、init、initialize 之類的,皆可以拿來使用
在使用 @PostConstruct
去初始化 Bean 的時候,在同一個 class 中,建議一次只讓一個方法加上 @PostConstruct
,不要同時在多個方法上,都加上 @PostConstruct
如果在同一個 class 中,同時有多個方法上面都加上 @PostConstruct
,雖然 Spring Boot 程式仍舊是可以正常運行起來,但是我們無法知道 Spring Boot 會先執行哪一個方法去初始化 Bean,因此可能會造成程式邏輯的錯誤,並且後續也很難統一管理初始化的設定
因此就建議大家,在同一個 class 內,一次只使用一個 @PostConstruct
,統一的去管理初始化的設定,這樣子不管是在維護上還是運作上,都是比較好的做法
上面的例子因為比較簡單,所以有的人可能會覺得「為什麼不直接在宣告 count 變數的同時,把 count 值也設成 5 就好?感覺用 @PostConstrcut
有點多此一舉?」,不過其實在實務上,@PostConstruct
的用途還是滿多的
使用 @PostConstruct
來初始化的強項在於 「@PostConstruct
可以進行複雜的初始化」,譬如說在 Map 裡生成預先定義好的數據、或是取得其他注入的 Bean 的資訊、或是檢查注入的 Bean 是否為 null 值….之類的,這些都是可以在 @PostConstruct
中做到的
因此在實務上,使用 @PostConstruct
來進行 Bean 的初始化是很常見的作法~
除了可以使用這篇文章所介紹的 @PostConstruct
去初始化 Bean 之外,其實也是有另一種方法可以去初始化 Bean 的,那就是「去實作 InitializingBean interface 裡面的 afterPropertiesSet 方法」,用這種寫法的初始化效果,是和使用 @PostConstruct
一模一樣的
不過因為「去實作 InitializingBean interface」算是比較舊的寫法,因此在此系列文中就沒有特別介紹到這部分,並且在實務上,也會建議大家盡量使用 @PostConstruct
來進行 Bean 的初始化
這篇文章介紹了要如何使用 @PostConstruct
,去對 Spring Boot 創建出來的 Bean 進行初始化,所以大家以後就可以透過 @PostConstruct
,將存放在 Spring 容器中的 Bean 的值,進行初始的出廠設定了
那到這篇文章為止,我們就算是對 Spring IoC 有了比較多的認識,我們已經了解了什麼是 IoC、DI,什麼又是 Spring 容器和 Bean,也知道要怎麼樣在 Spring Boot 中使用 @Component
、@Autowired
、@Qualifier
以及 @PostConstruct
這些註解,去對 Bean 進行創建、注入、以及初始化
那麼下一篇文章,我們會延伸出去介紹,要如何透過 @Value
這個註解,將 Spring Boot 設定檔中的值給讀取到 Bean 裡面,讓我們所寫的 Java 程式可以去運用 Spring Boot 設定檔中的值,那麼我們就下一篇文章見啦!