1. 程式人生 > >當建立物件時......

當建立物件時......

"程式設計師要建立物件了,快去西天請Spring'佛祖'。"  一大早我就聽到Tomcat在那裡大喊。

“不就是建立一個物件嗎,你給JVM老大打個電話,請他在堆裡邊new出來不就結了?無非就是一片兒記憶體而已。”我問道。

“唉,你不知道,這不僅僅是物件的建立,更是物件的裝配,要依賴注入,要初始化,又要代理什麼的..... 這事兒Spring最擅長。”Tomcat感慨到。

Spring慢悠悠地來了:“想安靜地喝一會兒茶都不行!讓我瞧瞧,這個要建立的物件是單例嗎? 嗯,果然是單例,也許之前建立過!讓我從我的快取中找找有沒有! ”

Spring在他的快取中扒拉半天,沒有找到,不滿地說:“快取中沒有,看來得忙碌一番了。”

他請JVM老大把要建立物件的類PetStoreService 從方法區取過來, 檢查了一下,嘆了口氣。

我問道:“先生為何發愁啊?”

Spring說:“這個類沒有預設建構函式,你看看,它依賴AccountDao和ItemDao,我還得先把這兩個bean給建立起來,然後才能呼叫這個建構函式建立這個PetStoreService物件,很麻煩的。”

public PetStoreService(AccountDao accountDao, 
       ItemDao itemDao){
    this.accountDao = accountDao;
    this.itemDao = itemDao;
}

我估計這個所謂的bean 就是一個java物件, 怪不得Tomcat說Spring做的主要是裝配工作,此言不虛啊。

Spring 把當前的建立工作先放下,把工作重心轉移到AccountDao, 照例還是要先看建構函式,這次運氣不錯,有個預設的、無引數的建構函式。

我說:“這下可以把它給new 出來了吧!”

Spring說:“不不,在讓JVM把它new 出來(這叫例項化)之前,我需要看看程式設計師有沒有給我設定一些需要預先執行的程式碼, 如果有,我得先執行。 同理,例項化之後,還得做類似事情。”

Spring先執行了所謂“前置程式碼”,然後用反射的方式通知JVM把物件給建立起來。

注: 事實上在JVM那裡還有一番折騰:

(1) 先執行AccountDao中例項變數的初始化 

(2) 執行例項程式碼塊 

(3) 最後才是執行建構函式,把AccountDao建立起來,返回給Spring。

拿到了AccountDao的例項,Spring馬上執行"例項化"以後的"後置程式碼"。

我對他深表同情:“不容易,這樣一個物件就ok了,可以返回給程式設計師了吧?”

Spring說道:“哪有那麼簡單!還有一步,叫做初始化,需要呼叫程式設計師指定的初始化方法。”

“初始化的前後也需要呼叫程式設計師設定的程式碼吧?”

“沒錯,就是這樣,哎呀,你看看,這個AccountDao中還有@Autowired註解,需要注入一個User物件,我還得處理一下,真是麻煩!”

Spring再次放下手頭工作,開始建立User物件,還是例項化,初始化,前置程式碼,後置程式碼,唉,這是一個遞迴的過程,我都懶得看了。

終於AcountDao物件建立完畢,接下來是ItemDao物件,又是一番同樣的折騰。

手持AccountDao物件和ItemDao物件, Spring終於可以開始建立PetStoreService物件了。

例項化,初始化,前置程式碼呼叫,後置程式碼呼叫, 都是熟悉的配方、熟悉的味道。

PetStoreService的物件已經創建出來(簡稱petStore),也已經初始化完畢,只剩下最後一步:初始化的後置程式碼呼叫。

Spring看了看相關配置,心裡咯噔了一下,說到:“壞了,這個PetStoreService 用了宣告式事務,我還得建立一個代理出來(簡稱petStoreProxy),在這個proxy中來呼叫事務相關的程式碼。”

“怎麼建立代理物件?” 我問道。

“我看看這個程式設計師想要的是petStore的兒子還是兄弟。”

“兒子? 兄弟?”

“哈哈,那是我的做的一個比喻,兒子就是這個PetStoreService類沒有實現介面, 我只好新建立一個類PetStoreServiceProxy,去繼承PetStoreService。 兄弟就是我建立的類PetStoreServiceProxy 和PetStoreService都實現同樣的介面。”

Spring看了看:“嗯,看來是'兒子',JVM老兄,你去把CGLib叫來吧,我得請他在執行時生成一個新的Class,這個新的Class要繼承PetStoreService。”

CGLib是個熱情洋溢的小夥子,迅速地在記憶體中建立了新的位元組碼, 把我看得目瞪口呆,這個世界上還真有直接寫位元組碼的人。

新的Class PetStoreProxy的位元組碼已經準備好,JVM把他裝載到方法區,Spring用它建立了一個物件出來,終於返回給了程式設計師!

“程式設計師拿到的物件可不是PetStoreService啊,他會發現的吧?” 我善意地提醒Spring。

“沒關係,兩個類的'介面'都是相同的,除非他檢查物件的所屬類,否則是意識不到的。再說了,哪個程式設計師會閒得無聊去檢視物件所屬的類啊。”

"佛祖"Spring折騰了半天, 又去悠哉遊哉地喝茶去了。