天天看點

spring aop設計模式_手把手教你用Java實作AOP

介紹

衆所周知,AOP(面向切面程式設計)是Spring架構的特色功能之一。通過設定橫切關注點(cross cutting concerns),AOP提供了極高的擴充性。那AOP在Spring中是怎樣運作的呢?當你隻能使用core java,卻需要AOP技術時,這個問題的解答變得極為關鍵。不僅如此,在進階技術崗位的面試中,此類問題也常作為考題出現。這不,我的朋友最近參加了一個面試,就被問到了這樣一個棘手的問題——如何在不使用Spring及相關庫,隻用core Java的條件下實作AOP。是以,我将在本文中提供一份大綱,幫助大家了解如何隻用core Java實作一個AOP(當然啦,這種AOP在功能上有一定的局限性)。注意,本文不是一篇有關Spring AOP與Java AOP的對比研究,而是有關在core Java中借助固有的設計模式實作AOP的教程。

想必讀者已經知道AOP是什麼,也知道在Spring架構中如何使用它,是以本文隻着眼于如何在不用Spring的前提下實作AOP。首先,我們得知道,Spring是借助了JDK proxy和CGlib兩種技術實作AOP的。JDK dynamic proxy提供了一種靈活的方式來hook一個方法并執行指定的操作,但執行操作時得有一個限制條件:必須先提供一個相關的接口以及該接口的實作類。實踐出真知,讓我們透過一個案例來了解這句吧!現在有一個電腦程式,用于完成一些數學運算。讓我們來考慮下除法功能,此時的問題是:如果core framework 已經具備了一份實作除法的代碼,我們能否在代碼執行時劫持(highjack)它并執行額外的校驗呢?答案是肯定的,我将用下面提供的代碼片段來證明這點。首先來看基礎接口的代碼:

spring aop設計模式_手把手教你用Java實作AOP

該接口實作類的代碼如下:

spring aop設計模式_手把手教你用Java實作AOP

假設我們既不能修該上面的代碼,也不能對核心庫進行任何改動,怎樣才能完美地實作校驗功能呢?不如試下JDK dynamic proxy的功能吧。

spring aop設計模式_手把手教你用Java實作AOP

讓我們通過測試類來看看由JDK dynamic proxy實作的校驗功能的效果如何。

spring aop設計模式_手把手教你用Java實作AOP

從結果可以看出,簡單地實作功能強大的InvocationHandler接口,我們便能得到一個hooking implementation。按照JDK文檔的描述,InvocationHandler接口是借助一個代理執行個體(proxy instance)來處理一個方法調用的。

現在我們已經知道,InvocationHandler的invoke()方法能夠幫助我們解決問題。那麼再來解決一個新問題——怎樣才能在方法執行的前後執行操作呢?說的更具體一些,我們能通過添加多個aop(before、after、around)來hook一個方法嗎(譯注:原文為add multiple aops,但我認為Handler是充當Aspect的角色)?答案同樣是肯定的。按照以下的步驟建立一個精簡的代碼模闆便能滿足這樣的需求:

  1. 建立一個抽象類,用于将aop應用于目标對象上。
  2. 建立名為BeforeHandler 和 AfterHandler的兩個aop。前者在方法執行之前工作,而後者則在方法執行結束後工作。
  3. 建立一個代理類,使所有的aop handler和目标對象隻需作為參數傳入,就能建立一個hook。
  4. 加入你自己的業務邏輯或者橫切關注點。
  5. 最後,通過傳入相關的參數建立代理對象(proxy object)。

技術實作概要

(譯注:此處是核心代碼片段,如果想運作該執行個體,需進入下方提供的連結下載下傳完整代碼)

建立一個handler的抽象類:

spring aop設計模式_手把手教你用Java實作AOP

建立名為BeforeHandler和AfterHandler的兩個易擴充的handler抽象類:

spring aop設計模式_手把手教你用Java實作AOP
spring aop設計模式_手把手教你用Java實作AOP

建立Proxy的工廠類:

spring aop設計模式_手把手教你用Java實作AOP

以下為測試代碼:

spring aop設計模式_手把手教你用Java實作AOP

配置

以上的代碼片段簡明扼要地解釋了AOP在結構上的實作(structural implementation)。當然,如果能通過實際的測試将其運用到現實中去,那就再好不過了。

spring aop設計模式_手把手教你用Java實作AOP