Spring AOP是我們?nèi)粘i_(kāi)發(fā)中經(jīng)常使用的工具,常被用來(lái)做統(tǒng)一的日志、異常處理、監(jiān)控等功能,使用方法在此不多贅述,有興趣的讀者可以自行去網(wǎng)上查閱資料進(jìn)行學(xué)習(xí),我們以注解的使用方式為例,分析其相關(guān)源碼,其他方式大同小異。
開(kāi)啟Spring AOP注解方式首先要配置標(biāo)簽,我們就以這個(gè)標(biāo)簽的解析作為入口來(lái)分析,這里需要讀者對(duì)Spring自定義標(biāo)簽解析的過(guò)程有一定的了解,筆者后續(xù)也會(huì)出相關(guān)的文章。鎖定AopNamespaceHandler:
這里提到了proxy-target-class和expose-proxy兩個(gè)屬性,簡(jiǎn)單介紹一下,Spring提供了JDK動(dòng)態(tài)代理和CGLIB代理兩種方式為目標(biāo)類創(chuàng)建代理,默認(rèn)情況下,如果目標(biāo)類實(shí)現(xiàn)了一個(gè)以上的用戶自定義的接口或者目標(biāo)類本身就是接口,就會(huì)使用JDK動(dòng)態(tài)代理,如果目標(biāo)類本身不是接口并且沒(méi)有實(shí)現(xiàn)任何接口,就會(huì)使用CGLIB代理,如果想強(qiáng)制使用CGLIB代理,則可以將proxy-target-class設(shè)置true,這兩種代理方式在使用的時(shí)候有一些需要注意的事項(xiàng),JDK動(dòng)態(tài)代理是基于實(shí)現(xiàn)目標(biāo)類的接口來(lái)創(chuàng)建代理類的,所以只有接口方法會(huì)被代理,其他方法不會(huì)被代理,而CGLIB代理是基于繼承目標(biāo)類實(shí)現(xiàn)的,所以不能被繼承的方法(例如final修飾的方法、private修飾的方法等)是不能被代理的,建議盡量使用JDK動(dòng)態(tài)代理的方式創(chuàng)建代理類。expose-proxy用來(lái)解決對(duì)象內(nèi)部this調(diào)用無(wú)法被切面增強(qiáng)的問(wèn)題,例如我們?cè)贏類的對(duì)象內(nèi)部x方法中調(diào)用另外一個(gè)內(nèi)部方法y時(shí),y方法不會(huì)被切面增強(qiáng),這時(shí)可以配置expose-proxy為true并將this.y()改為((A)AopContext.currentProxy()).y(),即可讓y方法被切面增強(qiáng)。
下面讓我們來(lái)看本篇文章的主角AnnotationAwareAspectJAutoProxyCreator的注冊(cè)過(guò)程。
*** 由于分析Spring源碼內(nèi)容較多,請(qǐng)?jiān)赪iFi環(huán)境下,點(diǎn)擊下方閱讀原文 ***
作者
張強(qiáng),16年加入京東,目前就職于京東商城京麥平臺(tái)組,從事京東對(duì)外開(kāi)放平臺(tái)和服務(wù)于第三方入駐商家的相關(guān)工作,開(kāi)源愛(ài)好者,對(duì)常用開(kāi)源框架如Spring、Mybatis、Dubbo等有源碼級(jí)別的了解,熱衷于研究各種技術(shù),致力于成為一名有腔調(diào)的工程師