1荷辕、CoreController
1)剛進(jìn)入類CoreControllerImpl.java
會(huì)看到:private static ThreadLocal if = new ThreadLocal();?
ThreadLocal 在execute()方法起始的地方:setContext(var1); 意思是將context放入ThreadLocal言询,那么context就可以在該線程的任何地方可見(jiàn)瞒渠,不用再通過(guò)傳參的方式將其往下傳钞啸。(常見(jiàn)例子:public void init(Context context){...}? context直接可以拿來(lái)用)
finally結(jié)束的地方:setContext((Context)null); 意思是釋放掉ThreadLocal線程結(jié)束襟齿,context也隨之消失。
2)CoreController.execute()方法如下:
public void execute(Context var1)throws PeException {....}
下面我們?cè)敿?xì)分析下execute()方法:
1)? 由pe框架簡(jiǎn)介4--MainController可知寞冯,var1的類型為LocalServletContext渴析,通過(guò)下面的類圖可以看出LocalServletContext實(shí)現(xiàn)了TransactionConfigAware,所以execute()方法上來(lái)進(jìn)入if分支吮龄,此時(shí) var1 為localServletContext俭茧。
2)由var2 = (TransactionConfig)this.getApplicationContext().getBean(var1.getTransactionId()) 知, var2 為transaction中的id所指明的bean螟蝙。例如下圖的PrintBillByQRCodeQuery恢恼。
問(wèn)題:Context.setTransactionId()民傻;在哪里體現(xiàn)胰默??我們需要注意:((TransactionConfigAware)var1).setTransactionConfig(var2); 將Context.TransactionConfig屬性已經(jīng)設(shè)置為transaction中的id漓踢,后續(xù)會(huì)用Context.getTransactionConfig()獲取相應(yīng)的transaction牵署。
3)最關(guān)鍵的便是:Chain var3 = var2.getTemplate().getChain();
該句是指找到 template.xml 中的相應(yīng)模板的chain,對(duì)應(yīng)下圖的例子就是找到?template.xml? 中?id="queryTemplate" 的chain :?chain="chainForRoleControlMV" 喧半。
問(wèn)題:Context.setTemplate().setChain()在哪里體現(xiàn)奴迅??
4)?var3.execute(var1, (Map)null); 便是調(diào)用?Chain.execute()方法挺据,由于Chain接口的實(shí)現(xiàn)類只有一個(gè):ChainImpl取具,所以執(zhí)行的方法為為ChainImpl.execute();
其中實(shí)現(xiàn)類ChainImpl實(shí)現(xiàn)了Chain扁耐、Command接口暇检。
2、ChainImpl.execute()方法關(guān)鍵步驟如下:
1)var3 = var12.execute(var1,this.else);
其中 var12 為 var9 的子集婉称,而?var9? 為 this.new 块仆,this.new (見(jiàn)下圖)就是chain.xml中的各個(gè)command;
到此王暗,我們就可以執(zhí)行各個(gè)command.execute()方法了悔据。
2)if (case ||char || var3) {? break; } 我們注意到:
(a)在循環(huán)執(zhí)行各個(gè)command.execute()方法時(shí),如果execute()方法返回結(jié)果為true俗壹;則跳出循環(huán)科汗,不再執(zhí)行后續(xù)的command。即如果chain中的commond在按順序執(zhí)行時(shí)绷雏,遇到一個(gè)返回true肛捍,則剩余的commond不再繼續(xù)執(zhí)行隐绵。所以開(kāi)發(fā)的時(shí)候需要注意,如果想讓commond都執(zhí)行一遍拙毫,程序中commond的實(shí)現(xiàn)類必須要返回false依许,返回true和異常的場(chǎng)景,不會(huì)繼續(xù)執(zhí)行接下來(lái)的commond缀蹄。
? (b)如果execute()方法拋出異常峭跳,則catch住(見(jiàn)圖2-1),并跳出循環(huán)缺前,之后對(duì)異常的處理都轉(zhuǎn)化為PE框架的異常蛀醉,見(jiàn)圖2-2
(c)對(duì)于圖2-2的上半部分,我們可以看到還有一個(gè)對(duì)var9的循環(huán)處理衅码,var9 此時(shí)為?this.try拯刁,this.try(見(jiàn)圖2-3)即實(shí)現(xiàn)Terminator的commond,其中this.new中已經(jīng)排除它逝段,在這里單獨(dú)處理這些類型的commond垛玻。
3)我們來(lái)看個(gè)Commod的例子:DateStyleCommod例子如下:
(a)根據(jù)DateStyleCommod找到實(shí)現(xiàn)類:com.ceb.wap.mgmt.core.DateStyleCommod
? (b)執(zhí)行DateStyleCommod.execute()方法,即執(zhí)行父類AbstractChannelCommand.execute()方法
(c)父類的execute()調(diào)用抽象的channelExecute()奶躯,通過(guò)策略模式帚桩,讓各個(gè)子類自己實(shí)現(xiàn)channelExecute()方法
4)特殊的commond:DelegateCommand
每一個(gè)Chain必須有一個(gè)而且僅限于一個(gè)DelegateComand(但是DelegateComand并不一定能執(zhí)行到,一旦有一個(gè)Command返回true或者跑異常嘹黔,則不會(huì)繼續(xù)執(zhí)行剩余的Command账嚎,證明代碼有異常或者校驗(yàn)不通過(guò)的情況)儡蔓;
?當(dāng)Chain執(zhí)行到DelegateCommand時(shí)郭蕉,開(kāi)始執(zhí)行Template,所以DelegateCommand要放在所有Command的最后喂江;
5)由DelegateCommand源碼可以看出召锈,當(dāng)執(zhí)行到DelegateCommand時(shí),開(kāi)始執(zhí)行Template.execute()开呐,即執(zhí)行tempalte.xml中對(duì)應(yīng)class的execute()烟勋。
我們選取Template的其中一個(gè)實(shí)現(xiàn)類ExecutableSequenceTemplate來(lái)看一下。
(a)?ExecutableSequenceTemplate 繼承AbstractSequenceTemplate 筐付,所以執(zhí)行父類AbstractSequenceTemplate .execute()卵惦。
? (b)?AbstractSequenceTemplate .execute()方法:見(jiàn)圖2-10? 。首先它獲取template.xml中的actions瓦戚,如果actions為空沮尿,則取transaction里的action執(zhí)行,否則執(zhí)行Template里的action。?
? (c)? ? 由圖2-11可知畜疾,? 如果var2不為空赴邻,即 transaction里的action,或者Template里的action有一個(gè)不為空啡捶,就循環(huán)執(zhí)行:
? ? ? ? ? Action var4 =this.getAction((String)var3.next(), var1);? ?? ?具體邏輯見(jiàn)? 圖2-12
? (d)??圖2-12 便是 怎么從Template里的actions 執(zhí)行到??transaction里的actions 里的關(guān)鍵
? ? ? ? ?Map var3 = var2.getTransactionConfig().getActions();? //首先獲取transaction里的action
? ? ? ? ?//?如果?transaction里的action 為空姥敛,返回Template里的actions? ? ?
? ? ? ? if (var3 == null) { var4 = this.getActions().get(var1); return (Action)var4;}?
? ? ? ?//??如果?transaction里的action 不為空
? ? ? ? var4 = var3.get(var1);? ?
? ? ? ? if (var4 == null) {??
????????????????var4 = this.getActions().get(var1);
????????????}?
//?由圖2-11可知 ,var1 為?transaction里的action 的ref的name,如:aftaction瞎暑、action彤敛、preAction等,var3? 是?Template里的actions的map(ref的name,ref的值) 了赌,這句話是說(shuō)墨榄,從?var3 (?Template里的actions??)中取出與var1(??transaction里的action?)的ref相同的name,一般 :?
? ? ? ?transaction :<ref name="action">Placeholder</ref>?? ? ? var1 :??action?
? ? ? Template? :<ref name="action">PrintBillByQRCodeAction</ref>? ? ?var3: map(action 勿她,PrintBillByQRCodeAction)??
? ? ?也就是說(shuō)袄秩,獲取 var3:map(?action ,PrintBillByQRCodeAction) 中key為?var1的value逢并,即將Template???中ref.name 與transaction?中?ref.name 相同的action替換為??transaction 的action之剧,這樣便開(kāi)始執(zhí)行transaction .action。
? ? ?如果var4 == null 還繼續(xù)執(zhí)行Template? 中的action筒狠。
? ? ?為了最后執(zhí)行transaction .action猪狈,必須先將?Template? 中的action執(zhí)行完箱沦,那么?Template? 中與transaction 重名的action(ref.name相同辩恼,即action)必須寫在最后。