Spring對(duì)AOP的支持
Spring中AOP代理由Spring的IOC容器負(fù)責(zé)生成吐句、管理,其依賴(lài)關(guān)系也由IOC容器負(fù)責(zé)管理店读。因此嗦枢,AOP代理可以直接使用容器中的其它bean實(shí)例作為目標(biāo),這種關(guān)系可由IOC容器的依賴(lài)注入提供屯断。Spring創(chuàng)建代理的規(guī)則為:
1文虏、默認(rèn)使用Java動(dòng)態(tài)代理來(lái)創(chuàng)建AOP代理侣诺,這樣就可以為任何接口實(shí)例創(chuàng)建代理了
2、當(dāng)需要代理的類(lèi)不是代理接口的時(shí)候氧秘,Spring會(huì)切換為使用CGLIB代理年鸳,也可強(qiáng)制使用CGLIB cglib是一個(gè)強(qiáng)大的,高性能,高質(zhì)量的Code生成類(lèi)庫(kù)。它可以在運(yùn)行期擴(kuò)展Java類(lèi)與實(shí)現(xiàn)Java接口丸相。cglib封裝了asm搔确,可以在運(yùn)行期動(dòng)態(tài)生成新的class。cglib用于AOP灭忠,jdk中的proxy必須基于接口膳算,cglib卻沒(méi)有這個(gè)限制。
原理區(qū)別:
- 實(shí)現(xiàn)方法: java動(dòng)態(tài)代理是利用反射機(jī)制生成一個(gè)實(shí)現(xiàn)代理接口的匿名類(lèi)弛作,在調(diào)用具體方法前調(diào)用InvokeHandler來(lái)處理涕蜂。而cglib動(dòng)態(tài)代理是利用asm開(kāi)源包,對(duì)代理對(duì)象類(lèi)的class文件加載進(jìn)來(lái)映琳,通過(guò)修改其字節(jié)碼生成子類(lèi)來(lái)處理机隙。
- 限制規(guī)則: 對(duì)于基于接口動(dòng)態(tài)代理的AOP事務(wù)增強(qiáng)來(lái)說(shuō),由于接口的方法都必然是public的刊头,這就要求實(shí)現(xiàn)類(lèi)的實(shí)現(xiàn)方法也必須是public的(不能是protected黍瞧、private等)诸尽,同時(shí)不能使用static的修飾符原杂。所以可以實(shí)施接口動(dòng)態(tài)代理的方法只能是使用“public”或“public final”修飾符的方法, 其他方法不可能被動(dòng)態(tài)代理您机,相應(yīng)的也就不能實(shí)施AOP增強(qiáng)穿肄。基于CGLib字節(jié)碼動(dòng)態(tài)代理的方案是通過(guò)擴(kuò)展被增強(qiáng)類(lèi)际看,動(dòng)態(tài)創(chuàng)建其子類(lèi)的方式進(jìn)行AOP增強(qiáng)植入的咸产。由于使用final、static仲闽、private修飾符的方法都不能被子類(lèi)覆蓋脑溢,相應(yīng)的,這些方法將無(wú)法實(shí)施AOP增強(qiáng)赖欣。
事務(wù)管理
方法的可見(jiàn)度和 @Transactional
在使用代理的時(shí)候屑彻,@Transactional 注解應(yīng)該只被應(yīng)用到 public 可見(jiàn)度的方法上。 如果你在 protected顶吮、private 或者 package-visible 的方法上使用 @Transactional 注解社牲,系統(tǒng)也不會(huì)報(bào)錯(cuò), 但是這個(gè)被注解的方法將不會(huì)執(zhí)行已配置的事務(wù)設(shè)置悴了。如果你非要注解非公共方法的話搏恤,請(qǐng)參考使用AspectJ
針對(duì)事務(wù)當(dāng)中有些內(nèi)部方法(有一些內(nèi)部方法我們不希望放在接口中防止被誤用)违寿, 我們就無(wú)法用@Transactional 來(lái)解決了。 那么我們可以單獨(dú)寫(xiě)一個(gè)事務(wù)的實(shí)現(xiàn)類(lèi)熟空, 并將需要事務(wù)執(zhí)行的代碼當(dāng)做參數(shù)傳給這個(gè)類(lèi)中的方法藤巢。