bean 初始化<clinit> <init> 初探
java文件編譯後會爲每個類自動生成一個<clinit>和<init>函數。
<clinit> 函數是在類第一次加載到jvm方法區的時候調用,實現對類中的一些靜態變量賦值以及執行靜態語句塊。
<init>是在對象實例初始化時候調用,對類中的一些變量賦值以及執行一些語句塊。
我們還可以通過在Spring中配置的init-method,以便在bean初始化完全之前做一些操作。配置格式如下
<bean id="beanInit" class="com.study.BeanInit" init-method="init" destroy-method="destory"></bean>
實驗示例代碼:
public class BeanInit{
private String init;
{
init = "init";//<init>
}
static private String cinit;
static {
cinit = "cinit";//<clinit>
}
private void init(){
init = "init-method";//init
}
private void destory(){
}
}
單步調試,觀察堆棧信息
首先被調用的是<clinit>函數。
其次被調用的是<init>函數。
最後是init。
(——這裏編譯生成的<init>是有一堆尖括號的,而我們自己定義的是init)
發現<clinit>和<init>的調用棧是一致的,都是在構造函數Constructor函數中被調用。
spring在獲取對象實例的時候,會調用類的構造函數Constructor,此時發現該類並沒有加載至內存,於是classLoader這時會加載這個類,而<clinit>就是在加載過程的初始化這一步被調用的,用來初始化這個類,這時該類已經加載在內存裏,接下來便會觸發<init>來初始化這個對象。
這裏的Constructor函數是編譯器自動生成的默認無參數的構造函數。