1 概述
????????? 介紹完Spring AOP所具備的功能特性,接下來,看一下再應用程序中使用AOP時應該遵循哪些最佳實踐。
2 活用切點表達式
????????Spring AOP的一大特色在于在開發人員提供了非常靈活的切點機制。Spring在編譯期間處理切入點,并嘗試進行優化匹配。然后,檢查代碼中的匹配規則將是一個代價高昂的過程。因此,為了獲得最佳性能,需要仔細考慮想要實現的目標,并盡可能縮小搜索或匹配條件的范圍。在前面已經看到過一個切點表達式,如下:
@Pointcut("execution(* com.jay.aop.service.AccountService.doAccountTransaction(..))")public void doAccountTransaction(){}
? ? ? ? 在這里的execution()代表的就是表達式的主體,它的基本語法如下,其中“?”部分表示可選項。
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(paramPattern)throws-pattern?)? ? ? ??????????
? ? ? ? 這個表達式看似復雜,但是逐步分解所有的模式,它們其實就是描述了一個方法的特征。
? ? ? ? modifiers-pattern:表示方法的修飾符
? ? ? ? ret-type-pattern:表示方法的返回值
? ? ? ? declaring-type-pattern:表示方法所在的類的路徑
? ? ? ? name-pattern:表示方法名
? ? ? ? param-pattern:表示方法的參數
? ? ? ? throws-pattern:表示方法拋出異常。
? ? ? ? 這些模式的作用就是完成切點的匹配。在各個模式中,可以使用"*"來表示匹配所有選項。Spring AOP還為開發人員提供了一組非常有用的描述符來簡化切點表達式的使用過程。例如,args描述符表示方法的參數屬于一個特定的類;within描述符表示方法屬于一個特定類;target描述符表示方法所屬的類等。
? ? ? ? 為了獲得良好的性能,在設計切點表達式時,至少應該包含方法和類型模式。這并不是說如果只使用方法或類型模式中的一種,匹配就會不生效,而是因為類型模式的匹配過程非常快,它通過快速選擇無法進一步處理的連接點來縮小搜索空間。同時,建議在空方法上聲明切點,并通過空方法引用這些切點。
? ? ? ? 另一種最佳實踐在于盡量聲明小的切點,并把它們組合起來構建復雜的切點。下面代碼展示了定義小切點并將它們連接起來的代碼實例。
@Pointcut("execution(public * *(..))")private void anyPublicMethod(){}@Pointcut("execution(* com.jay.aopproxy.service.impl.AccountServiceImpl.doAccountTransaction(..))")public void doSomething(){}@Pointcut("anyPublicMethod() && doAccountTransaction()")private void transactionOperation(){}
? ? ? ? 這里的transactionOperation()就是由anyPublicMethod()和doAccountTransaction()這兩個切點組合而成的。
3 Spring AOP面試題分析
3.1 Spring AOP是基于什么技術體系實現的?
? ? ? ? 解答:Spring AOP的實現依賴代理機制。代理機制在具體實現上一般有兩種方式,一種是靜態代理機制,一種是動態代理機制。Spring AOP基于動態代理模式提供了面向切面機制。
3.2 Spring AOP提供了那些類型的通知機制?
? ? ? ? 解答:Spring AOP的通知機制類型非常豐富,開發人員可以在方法執行之前、之后、前后、返回以及拋出異常時實現各種自定義的通知邏輯。而且,Spring AOP實現通知的方式使用注解來標記,這些注解包括@Before、@After、@Around、@AfterReturning和@AfterThrowing等,分別對應于方法執行的各個階段。
3.3 Spring AOP使用了哪幾種動態代理機制?性能上哪種更優?
? ? ? ? 解答:常見的動態代理實現技術包括JDK自帶的代理類、第三方的CGLIB和javassist。Spring AOP使用的是JDK和CGLIB。從性能上講,JDK動態代理效率高于CGLIB。
3.4 如果想要在一個類的內部方法實現AOP,有什么辦法?
? ? ? ? 解答:關于Spring AOP有一點需要注意,只能在方法的調用過程中嵌入通知機制。這是一個很重要的限制,會導致對同一個類中的內部方法無法有效地實施動態代理。這是用可以使用Spring AOP提供的AopContext上下文對象來獲取當前的AOP代理。AopContext是一個非常有用的工具類,想要獲取該類,需要確保ProxyFactoryBean的exposeProxy屬性被設置為true。
3.5 如果想要基于Spring AOP實現對切點的精細化管理,有什么策略?
? ? ? ? 解答:Spring AOP創建切點的方式是非常靈活的,Spring專門提供了一個execution()配置方法。可以根據方法的修飾符、返回值、類路徑、方法名、方法參數以及異常信息來設置方法調用與切點的匹配規則。這是實現精細化管理的一個維度。
? ? ? ? 第二個精細化管理的維度是設置切點的粒度。可以盡量聲明小的切點,并把它們組合起來構建復雜的切點。這樣,切點之間就具備了靈活的可重用性以及組合性。
? ? ? ?