Aspect Oriented Programming(AOP) - The first sight
AOP 是個程式編寫方式,透過允許橫切的方式分離並且模組化,能在不修改程式碼本身就能添加額外的程式碼。接下來介紹 Spring實作的 AOP 與library AspectJ。
圖片出處 www.baeldung.com
AOP
Aspect - 標準的程式碼功能分散在分散在application中多個位置點,每個aspect專注於特定的橫切功能
Joinpoint - 程式執行過程的的特殊點,例如method 執行、call建構子、參數被指定, etc
Advice - 於在特定的joinpoint的aspect中採取行動
Pointcut - match joinpoint的正規表示法,當join point match 的pointcut, 與pointcut相關的特定advice會被直執行
Weaving - 連結aspects 與目標物件來建立advised 物件的process
Business Object - 一般的邏輯物件,像是兩個參數相加
public class SampleAdder {
public int add(int a, int b) {
return a + b;
}
}
Aspect - 能跨多個class的模組化類別
public class AdderAfterReturnAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public void afterReturn(Object returnValue) throws Throwable {
logger.info("value return was {}", returnValue);
}
}
以上就是個簡單在物件,當關聯物件return之後,會寫log。此時還沒有任何Spring annotation去做關聯。
Joinpoint - 執行程式中的連接點,例如執行method或處理exception。
在Spring AOP中,JoinPoint通常是在程式執行的時候。
Pointcut - 切入點是個predicate(謂詞是一個會回傳boolean的function),藉由Aspect的joinpoint協助match到需被執行advice 。
Advice與pointcut expression做關聯,在任何joinpoint 被pointcut match 到時Advice會被執行。
Advice - 在aspect的特定join point時,執行 的一個動作。包含 around, after, before的advice類型。
In Spring, advice是個攔截器圍繞在所有joinpoint
Wiring Business object and Aspect
<bean id="sampleAdder" class="org.baeldung.logger.SampleAdder" />
<bean id="doAfterReturningAspect"
class="org.baeldung.logger.AdderAfterReturnAspect" />
<aop:config>
<aop:aspect id="aspects" ref="doAfterReturningAspect">
<aop:pointcut id="pointCutAfterReturning" expression=
"execution(* org.baeldung.logger.SampleAdder+.*(..))"/>
<aop:after-returning method="afterReturn"
returning="returnValue" pointcut-ref="pointCutAfterReturning"/>
</aop:aspect>
</aop:config>
由定義得知,建立一個aop:aspect 去reference到該aspect bean。point cut設定expression去偵測程式執行business object時是否有被match到。而after-returning則是其中一種advice,當reference到的point cut,則會在business object method回傳之後去執行advice 定義的method。
更多AOP相關Annotation, 可參閱上方 Spring Bean annotation 的 Stereotype Annotation and AOP
AspectJ
除了實作AOP外更加強compile-time, post-time, and load-time weaving效能的改進。
AspectJ Runtime - 當執行AspectJ程式, class path 必須含有classes以及AspectJ runtime library jar.
AspectJWeaver - 除了AspectJ外,還需要weaver.jar引入
Aspect creation
AspectJ 實作以下三個AOP功能:
- Join point
- point cut
- advice
以下介紹3種如何weave accepts into code
- Compile-Time Weaving: 當我們有source code與aspect code,AspectJ compiler 將會把兩者進行編譯,出來的source code就能當作一般java class執行。從config 設定showWeaveInfo = true就能在執行程式時看到aspect載入狀況。
- Post-compile Weaving: 也可稱之為binary weaving,編織已存在的class files與jar files. config中加入jar的artifact於weaveDependencies中
- Load-time weaving: 直到class loader loads class file to JVM才去做weaving,由於是需要run time環境,因此需要啟動weaving agent。藉由設定aop.xml去定義 Aspects會被哪些weaving用到,以及根據不同類型weaver的執行條件等。
Annotating Aspects 範例
在aspect class上加@Aspect annotation ,用@Pointcut去指定weaving對象,用@Around這個advice於某個joinpoint,並撰寫邏輯後執行 ProceedingJoinPoint.proceed()
此外其他Annotation小知識
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Secured {
public boolean isLocked() default false;
}
以上就是定義一個@Secured的annotation,並只能在Method上加註,且提供預設為false的isLocked()參數。
兩者差異
Spring AOP and AspectJ 可以從capabilities, goals, weaving, internal structure, joinpoint, simplicity來看
Capabilities and goals
Spring AOP 實作簡單的AOP來提供跨 Spring IoC ,由於只能管理Spring Container的bean,並非是完整的AOP solution。AspectJ目標則是提供完整的AOP solution,功能強大、複雜且全面。
Weaving
Spring AOP and AspectJ各自使用不同類型的weaving行為,會影響到效能跟易用性。AspectJ的三種方式上面篇提過。AspectJ 是用compile-time 與class load time weaving,Spring AOP則是用runtime weaving。在runtime weaving,aspects在應用程式執行期間透過目標物件proxy進行weave。(JDK dynamic proxy或GCLIB proxy)
Internal Structure and Application
Spring AOP 是個proxy-based AOP framework,意味著要去透過實作interface 或繼承target object來做到與Aspect溝通。AspectJ 則直接compile去weave aspect to code。
Joinpoint
由於Spring AOP based on proxy pattern, 因此無法處理static, final的方法,因為無法被override in runtime。
AspectJ 則是在運行之前的compile time處理完,因此target又更廣,如:method call, method execution, handler execution, etc。
Simplicity
Spring AOP 顯然是更簡單的實作方式,不必在執行過程加入額外編譯器。AspectJ因為需要額外的compiler也表示需要引入AspectJ到開發者的IDE or build tool。
Performance
compile-time 肯定是快過 runtime weaving.
總結
Spring AOP | AspectJ |
---|---|
Implemented in pure Java | Implemented using extensions of Java programming language |
No need for separate compilation process | Needs AspectJ compiler (ajc) unless LTW is set up |
Only runtime weaving is available | Runtime weaving is not available. Supports compile-time, post-compile, and load-time Weaving |
Less Powerful – only supports method level weaving | More Powerful – can weave fields, methods, constructors, static initializers, final class/methods, etc… |
Can only be implemented on beans managed by Spring container | Can be implemented on all domain objects |
Supports only method execution pointcuts | Support all pointcuts |
Proxies are created of targeted objects, and aspects are applied on these proxies | Aspects are weaved directly into code before application is executed (before runtime) |
Much slower than AspectJ | Better Performance |
Easy to learn and apply | Comparatively more complicated than Spring AOP |
references:
留言
張貼留言