当创建对象时......
"程序員要創建對象了,快去西天請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折騰了半天, 又去悠哉游哉地喝茶去了。
總結
以上是生活随笔為你收集整理的当创建对象时......的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我也是一个线程,为什么每天累得像狗一样?
- 下一篇: 学习编程的加速度