Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Spring 2.0 技術手冊第四章 - Spring AOP

2,966 views

Published on

Spring 2.0 技術手冊

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Spring 2.0 技術手冊第四章 - Spring AOP

  1. 1. 。一之點重的節章個這是也 用使何如解了您讓,心 Spring AOP核的賴依所能功 子或架框子些一中 是也 而,術 Spring Spring AOP技種一的 現實是 AOP ,型 模 計 設 個 兩 的 成 相 輔 相 以 可 是 S pring AOP們 它,觸 抵 互 相 不 並) ( 跟 OOP O bject-oriented programming AOP 。釋解得獲將都中節章個這在,詞名的關相 與樣各式各上以,) AOP (合縫的式程用應與及計設 W eave的 Aspect 在重著 , 為之稱件 A spect-oriented programming Aspect物 殊 特 的 樣 這,件 物 個 一 為 計 設 來 出 立 獨 Crossing-cutting concerns將, 為 稱 輯 邏 的 樣 這 ,) Cross-cutting concerns 、 S ecurity Logging如例(輯邏務服統系的關無輯邏務商與入插中程流的務服個一在 Spring AOP 4
  2. 2. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 4.1 AOP 入門 過觸接未尚於對, AOP 名全 Aspect-oriented programming AOP 的 是像,解理以難人令詞名語術的象抽多許中 ,說來人 A OP Cross-cutting (制機理代從先將,中節小個這在,等 concerns A spect W eave 、 、 S pring 紹介 中 從 , 式 程 範 示的單 簡 且 際 實 個 一 看 來 ) 式 方 種 一 的 現 實 AOP AOP 。語術種各與念觀的 4.1.1 從代理機制初探 AOP 子例的見常單簡個一從先,邊一到放詞名寫縮文英個這 將先且暫 AOP 需常很中式程,作動) (誌日有含中當子例個這,題議個一看來 L ogging 為作是或,程過作運式程視檢後事在便以,錄記下作件事或作動些某為要 。訊資的時錯除 ,息訊誌日下留時法方些某行執在要需您當,子例的單簡最個一看來 : 寫 撰下如 會 能 可 您 , 的 覺 直 package onlyfun.caterpillar; import java.util.logging.*; public class HelloSpeaker { private Logger logger = Logger.getLogger(this.getClass().getName()); public void hello(String name) { // 錄記下留時始開行執法方 錄 logger.log(Level.INFO, "hello method starts...."); // 能功要主式程 System.out.println("Hello, " + name); // 錄記下留前畢完行執法方 錄記下留前畢完行執法方 logger.log(Level.INFO, "hello method ends...."); }4 2
  3. 3. 4 3 :面介 IHello 個一義定先首,說來子例的際實個舉 。責職關相務商留保僅以可就中當件物理代被此如,件 物的理代被叫呼再候時的要需在並,務服關相等誌日現實以可中件物理 代在,面介個一同現實須必件物理代被與件物理代,中現實的理代態靜在 理代態靜 。) D ynamic proxy (理代態動與) S tatic proxy ( 理代 態靜:式方 理代種兩論討邊這在,題問個這決解來制機) ( 理 代用使以可 P roxy 。 去 移 中 式 程 的 有既從 務 服 關 相 些 這 將 的 單簡法無您,碼式程的作動誌日下留有所改修要需將麼那,務服的)等理 管易交、查檢限權或(誌日要需再不若,法寫的上以用使,面方一另 。 碼式程 的 務 服 或 作 動 的 關相不 責 職 件 物 與 些 這 於少還 許 或 , 碼 式 程 的 佔 所責職的身本件物,責職的有負該身本件物了淆混至甚,重加形更擔負的 件物得使會,)等等理管易交、查檢限權如例(中之件物了入混也作動關 相 的 責 職 身 本 件 物 非 些 一 有 , 作 動 誌 日 有 只 不) S ervice (務 服 的 要 需 果 如 。大加度難困的碼式程誌日護維得使這,碼式程的作動誌日些這寫撰處到您 成造必勢法寫的上以,求需有都處到作動的誌日種這中式程果如想想 。責職的外額了加增 Speaker Hello- 得使這,)字文等 "Hello" 示顯(輯邏務商 HelloSpeaker 於屬不並作 動 個 幾 這 的 誌 日,說 來 HelloSpeaker 於 對,中 別 類 H elloSpeaker ) cutting C ross- (入切橫碼式程行幾這的誌日而然,作動誌日上加後前的行執法 方在,計設式程的上以如是就法作的單簡最,錄記下留能都時畢完行執與 始開行執法方望希您,時法方 hello() 行執當,中別類 HelloSpeaker 在 } Chapter 4 Spring AOP
  4. 4. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) StaticProxyDemo IHello.java package onlyfun.caterpillar; public interface IHello { public void hello(String name); } 的輯邏務商現實讓後然 HelloSpeaker 現實別類 IHello :如例,面介 StaticProxyDemo HelloSpeaker.java package onlyfun.caterpillar; public class HelloSpeaker implements IHello { public void hello(String name) { System.out.println("Hello, " + name); } } ,中其入插碼式程的誌日何任有沒在現中別類 HelloSpeaker 在,到看以可 介 現實要也樣同件物理代,中之件物理代至放被將現實的務服誌日 IHello :如例,面 StaticProxyDemo HelloProxy.java package onlyfun.caterpillar; import java.util.logging.*; public class HelloProxy implements IHello { private Logger logger = Logger.getLogger(this.getClass().getName()); private IHello helloObject; public HelloProxy(IHello helloObject) { this.helloObject = helloObject; }4 4
  5. 5. Chapter 4 Spring AOP public void hello(String name) { // 務服誌日 log("hello method starts...."); // 輯邏務商行執 helloObject.hello(name); // 務服誌日 log("hello method ends...."); } private void log(String msg) { logger.log(Level.INFO, msg); }} 誌 日 排 安 以 可 後 前 輯 邏 務 商 現 實 正 真,中 法 方 HelloProxy hello() 的別類 在 。件物理代用使何如看看來式程試測個一寫撰際實,務服 StaticProxyDemo ProxyDemo.javapackage onlyfun.caterpillar;public class ProxyDemo { public static void main(String[] args) { IHello proxy = new HelloProxy(new HelloSpeaker()); proxy.hello("Justin"); }} 物理代被個一它給須必時件物理代構建,件物理代是的行執叫呼中式程 來,面介 為面介作操換轉須必,時件物理代的回取作操在得記,件 IHello :果結的行執際實下一看 4
  6. 6. 4 6 。理原本基的理代解了您讓在是,的目的理代態靜紹介邊這在,任勝法無就時大稍模規式程在理代態靜,理代行進法方個每為要必勢,多很法方的理代要果如且而,件物的型類種一於務服只面介個一的件物理代,的到看所您如而然,例範本基的理代態靜是這 程流作運的制機理代 4.2 圖 :程流作運的制機理代出看步一進更來式方的解圖從以可,責職的它於心專以可 HelloSpeaker,作動誌日入介必不時寫撰在 HelloSpeaker 得使這,作動的誌日上加後前其在並,hello() 行執來 HelloSpeaker 的正真理代將 件物理代 HelloProxy 果結行執案專 4.1 StaticProxyDemo 圖 ) – http://openhome.cc 良信林(冊手術技 Spring 2.0
  7. 7. Chapter 4 Spring AOP 文 在現出都何為息訊誌日的 圖:問會人多很 4.1 " Hello, Justin" ? 嗎 錯 有 果 結 行 執 例 範 ?) 後 之 在 是 許 也 果 結 的 行 執 您 (前 之 字 不並作動誌日,行進來緒行執個一另由是作動的誌日,道知要 執有實確作動誌日於在點重的例範,程流式程)入介或(響影 來用是不也作動誌日,序順的現出台控主於息訊在是不而,行 順的息訊現出台控主到看想的真果如。用之序順行執式程測預 全份部的誌日將麼那,序順叫呼的法方與件物中式程合符,序 。可即出輸準標成改部 理代態動 件 物 定 特 為 必 不 您, 的 能 功 理 代 態 動 發 開 助 協 可 了 入 加 後 之 JDK 1.3 API 在 者理處個一得使以可,理代態動用使,件物理代的定特寫撰法方與 作實須必計設別類的者理處個一,先首。件物個各於務服) H andler ( java.lang.reflect.InvocationHandler 計 設 如 例,明 說 行 進 來 例 實 以,面 介 LogHandler :別類 個一 DynamicProxyDemo LogHandler.javapackage onlyfun.caterpillar;import java.util.logging.*;import java.lang.reflect.*;public class LogHandler implements InvocationHandler { private Logger logger = Logger.getLogger(this.getClass().getName()); private Object delegate; public Object bind(Object delegate) { this.delegate = delegate; return Proxy.newProxyInstance( delegate.getClass().getClassLoader(), 4 7
  8. 8. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) delegate.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try { log("method starts..." + method); result = method.invoke(delegate, args); logger.log(Level.INFO, "method ends..." + method); } catch (Exception e){ log(e.toString()); } return result; } private void log(String message) { logger.log(Level.INFO, message); } } 物理代個一立建法方態靜 用使是念概的要主 Proxy.newProxyInstance() 的立建所作操以可您後之,面介的理代要所知告須必時件物理代立建,件 ,法方 的 行執會時作操次每在,件物理代 InvocationHandler invoke() 的行執要上際實,數參行執與稱名法方的件物理代被入傳會法方 invoke() ,作動誌日上加後前 在您, method.invoke() 由交法方 method.invoke() 。果結傳回的後過行執法方際實是件物的回傳 method.invoke() :如例,面介的理代要所義定須必樣同,理代態動現實要4 8
  9. 9. Chapter 4 Spring AOP DynamicProxyDemo IHello.javapackage onlyfun.caterpillar;public interface IHello { public void hello(String name);} 的輯邏務商現實讓後然 HelloSpeaker 現實別類 IHello :如例,面介 DynamicProxyDemo HelloSpeaker.javapackage onlyfun.caterpillar;public class HelloSpeaker implements IHello { public void hello(String name) { System.out.println("Hello, " + name); }} 介 的中案專 前之跟這,了到現發許或您的尖眼 StaticProxyDemo IHello 。現 呈 整 完 的 例 範 了 為 是 來 出 寫 撰 邊 這 在,容 內 的 同 相 是 H elloSpeaker 、面 定綁來法方 的 用使要您,式程的試測個一寫撰來下接 LogHandler bind() :示所下如,件物理代被DynamicProxyDemo ProxyDemo.javapackage onlyfun.caterpillar;public class ProxyDemo { public static void main(String[] args) { LogHandler logHandler = new LogHandler(); IHello helloProxy = (IHello) logHandler.bind(new HelloSpeaker()); helloProxy.hello("Justin"); }} 4
  10. 10. 4 1。碼 式程行一 何任改 修需不 身本式程 用應而 ,離脫 中式 程用應 從 接 直 Aspect些這將以可又,候時的務服關相要需不而,務服供提中之式程用應入介以可,候時的要必在,外之式程用應於立獨以可 Aspect ,下 之 計 設 的 好 在 。 為即詞名寫縮 AOP,Aspect-oriented programming 的謂所是就這,件物 的楚清責職個 Aspect一的件物務商定特入介不、用通為計設) C ross-cutting concerns (作動些這將 您 , 務 服 或 作 動 的類這 等 誌 日 是 像 以 可 的 指 所 的中 Aspect AOP 。) A spect (面切為之稱件物的樣這, LogHandler是或 HelloProxy 的範 示 中 例 範 前 之是像 , 件 物 務 服 個 一 為計設,來出取提務任或作動的關無輯邏務商與等誌日將件物理代用使。) C ross-cutting concern (點 切 關切橫為之稱中 在作動的樣這誌日 AOP,中程流行執式程的 HelloSpeaker 入) C ross-cutting (切橫碼式程的誌日 AOP,說 來語術的 在,重加責職的 HelloSpeaker 得使這,作動誌日入插須必卻,字文呼招示顯是責職的身本 H elloSpeaker ,中子例的頁 如 4.2 AOP ?係關何有 與子例個這,上題議的 到回 AOP 。在存的作動誌日到識意用不它,作動的誌日於關有何任入插用不也 HelloSpeaker 而,面介與件物定特於務服再不 LogHandler 果結行執的案專 4.3 DynamicProxyDemo 圖 :果結的行執下一看來 ) – http://openhome.cc 良信林(冊手術技 Spring 2.0
  11. 11. 4 11 :的純單很是 程 流 務 商 的 來 原 如 例,涵 意 的 Cross-cutting concerns 出調強可明說片圖以 。 Cross-cutting concerns 為之稱被中語術的 在作動些這,中之程流 AOP 理 處 的 件 物 個 各 至 插 安 到 見 被 常 中 之 式 程 用 應 些 一 在 ,) (務服的 S ervice 面層統系等) T ransaction (易交、查檢) S ecurity (全安如,作動的類這 誌 日 於 似 類 外 另,中 之 程 流 務 商 的 責 負 所 身 本 HelloSpeaker 至 入) cutting C ross- (切橫被先原作動的誌日,中子例的案專 DynamicProxyDemo 在 Cross-cutting concern AOP : 念 觀 與 語 術 的 紹 介 以 照 對 一 逐 來,例 範 的 制 機 理 代 紹 介 前之以將邊這,義意詞名其解理易容不並上面字從單,象抽於過都語術詞 名多許的 於關有, AOP Aspect-Oriented Programming 為名全 AOP 4.1.2 AOP 觀念與術語 。詞名文中的服信人令更無有看後日待留,題問詞名 的譯翻文中將,現呈來語術詞名文英的本原 以將,中節章 AOP 的來下接此因,詞名譯翻文中的一統個有沒也在現語術詞名文 英些這且而,口拗很在實文中成翻要語術詞名文英關相的 AOP Chapter 4 Spring AOP
  12. 12. 4 12專 DynamicProxyDemo 在 如 例,改 修 的 何 任 作 用 不 件 組 用 重 可 的 中 式 程 用應,離脫中式程用應從上馬以可也,候時的務服要需不,上之式程用應至) (合縫,候時的務服該要需在,來出立獨中程流務商從之將,認 W eave辨的 Aspect 於重著中 在。例實體具個一的 AOP 是就語術的 Aspect AOP在別類 L ogHandler ,別類 LogHandler 個一為計設作動的誌日將,中案專DynamicProxyDemo 在如例。 Aspect 為之稱件物些這,件物的用重可立獨個 各 計 設,來 起 集 收 Cross-cutting concerns 的中之輯邏務商個各於落散將 Aspect 。雜複為更寫撰的式程或 輯 邏 的 身 本 件 物 務 商 得 使,中 之 輯 邏 務 商 於 雜 混 Cross-cutting concerns,面方一另,譯編新重後然,碼式程的務服誌日寫撰有所改修須必則,務服該除移是或改修能功誌日的中件物將要天今您若,高增本成的式程護維得 使 會,中 程 流 之 件 物 的 務 商 某 責 負 在 寫 撰 接 直 若 Cross-cutting concerns 二之解圖 4.5 AOP 圖 :念概的 與 Cross-cutting concerns cuttingCross- 出示表解圖下以用使可則,段片式程查檢全安、誌日的關相入寫的生生硬被像中碼式程的件物,務服等查檢全安與誌日入加要了為在現 一之解圖 4.4 AOP 圖 ) – http://openhome.cc 良信林(冊手術技 Spring 2.0
  13. 13. 4 13 。後前的法方 至用應要 Advice 些哪明說, 寫撰中 Pointcut 或檔義定在以可 Annotation 您, 說 的 體 具 中 Spring 2.0 在。 務 服 供 提 上 式 程 用 應 至 合 縫 將, 時 Advice 式示表 Pointcut 合符法方的叫呼當, 的趣興感了義定 Jointpoint Pointcut Pointcut 。候時的生發外例個某中法方是或 ,) 有 都 者 兩 或 (後 之 或 前 之 行 執 被 法 方 個 某 是 能 可 機 時 行 執, Jointpoint 的法方援支只 S pring 。機時的行執被中式程用應在 是就,說來 Advice 體 具, Joinpoint 為之稱機時或點的程流務商入加時行執式程用應在 Advice Joinpoint 。務服的供 提要所或為行的 Cross-cutting concerns 了括包中 A dvice 。例實體具個一 的 Advice 是就,法方 的 中案專 invoke() LogHandler DynamicProxyDemo 是像,的作實何如是碼式程誌日括包會中 Advice ,言而作動的 誌日以。 Advice 為之稱作實體具的 Cross-cutting concerns 對中當 Aspect Advice 。合耦生發架框式程用應的前目與 而務服些某了入加前目為因會不而,中之式程用應的它其至用應件組些這 將以可您,性用重的件組些這高提可而因,中之件組式程用應的用重可在 API 現出會不 的關相務服與,說的體具,在存否是件物的務服供提道知用 AOP 不 它,式 方 計 設 的 以,說 來 件 組 的 用 重 可 中 式 程 用 應 於 對,面 方 一 另 。碼式程的身本改修用不並時務服誌日要 需 它 在,件 組 的 用 重 可 中 式 程 用 應 是 就 色 角 的 表 代 所 的中案 HelloSpeaker Chapter 4 Spring AOP
  14. 14. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) Target 個一 Advice 如例,件物標目或象對的用應被 DynamicProxyDemo 中案專 的 HelloSpeaker 的 中 是就 LogHandler Advice Target 。 Introduction 類該改修用不而,為行加增其為以可 ,別類的存現個一於對 I ntroduction 期時行執在,別類的成完譯編、寫撰已個某為以可,說的體具,式程的別 。碼式程行一何任增新或改修用不而,為行或法方些一入加態動 Proxy E xpert One-on-One J2EE Development WIthout EJB ,中 書 一》 《在 R od 的要主個五有作實的 ,到提有中章八第在 Johnson J uergen Hoeller 、 A OP 、 D ynamic Proxies 、 :略策 D ynamic Byte Code Generation J ava Code 。 Generation 、 U se of a Custon Class Loader 、 L anguage Extensions 機理代過紹介例範式程的際實用使經已,中理代態動與理代態靜前之在 。 面 介 的 何 任 理 代 於 用 可,成 完 來 理 代 態 動 過 透 是 要 主 的 S pring AOP ,制 留 遺 些 一 是 像,別 類 理 代 以 用,理 代 S pring 用使以可也 CGLIB ,面 方 一 另 L egacy classes 。) (別類 Weave Advice 在,) (合 縫 為 之 稱 程 過 的 上 之 件 物 至 用 應 被 W eave AOP 的合縫中 (期 時 入 載 別 類、) (期 時 譯 編:點 間 時 個 幾 有 式 方 C ompile time C lassload time 。) R untime (期時行執、) 的體具詞名關相 的過紹介上以將,例實的 DynamicProxyDemo 合結 AOP :識認與解理的詞名個一每對於助有,示表來片圖用使4 14
  15. 15. Chapter 4 Spring AOP 圖 4.6 AOP 意示詞名個各的4.1.3 Spring AOP 在別差的要主,式方作實同不的念概 對其有會架框 的同不 AOP AOP) (合縫被何如們它及以,度程富豐的 Pointcuts A spects 、 的供提所於 W eave 。 等 式 方 的 理代 、 ) 式 方 義 定 的 Pointcuts 是像(式程用應至 的定特用使不而,寫撰來言語式程 用是 Spring Advices Java 的 AOP 的 寫 撰, 或案檔態組 用使以可時 Pointcuts 義 定 在, 言 語 XML Annotation 用以可就,法語的定特習學必不您,悉熟很都說來員人發開 於對式方 Java Java 。 用運來式格 與言語式程 的悉熟 XML Spring AOP 作實會 的 , API 現實來式方的 作實以擇選若 Advices Spring AOP AOP 的範規所)Alliance h ttp://www.sourceforge.net/ projects/aopalliance ( 這,) (畫計合聯的成組所體團多許由是 A OP Alliance ,面 介 J oint project 對是的目,範規面介的來出訂制循遵須必求要作實的 於對體團些 AOP Java 4 1
  16. 16. 4 16 。 理原的 作 運 後 背 其 解 理 易 容 會 , 時 式 方 定 設 AOP的新 Spring 2.0 用使在,節細多許的 Spring AOP 握掌以可您是處好,式方種 這是就 的 紹 介 要 先 首 , 時 Spring AOP 紹 介 始 開一章 本 , 件 物 理 代 定 設並, Advice 義定來 的中當AOP API Spring 作實須必您,式方的 現實 AOP本版前先或 Spring 1.2 是就也,式方的 Spring API 作實統傳是種一第 。式方的 現實種三了供提中 AOP 在 Spring 2.0 。性裝封的件物壞破會 Joinpoints 的員成 援支,為認中學哲計 Field設的 Spring 在為因是這, Jointpoints 的員成 援支不 ,用應被Field S pring後前的行執法方在將 Advices 是就也, 的法方援支只 Joinpoints Spring 。用使來) ( L egacy classes別類舊是或別類) T hird-party (方三第的碼始原動更法無些一讓是上本基式方個這且而,理代行進法無法方的 為告宣被於對以所,別類子生產 final須 必 於 由,式 方 的 Proxy classes 用 使,低 降 度 合 耦 的 間 之 此 彼 件 組 的 式 程用應 讓 以 可 這 , 先 優 為式方 的 面 介 作 實 以 該 應 您 , 中 在 Spring AOP 。) P roxy classes ( 別 類 理代為 作 別 類 子 個 一 生 產Targets為 CGLIB 用使會 Spring 則 , 面 介 作 實 不果如 , 理 代 態 動 行 進 來java.lang.reflect.Proxy 用使會期時行執在 則,面介的好義定先預作 Spring實 Targets讓以可您, Targets 至入導期時行執在是 的 Advices Spring 。定設件物理代的有所成完您為 Spring 由,示 標 接 直 中 之 別 類 在,式 方 的 Annotation用使擇選以可也您。 入導 Advices Targets 為以可就,訊資關相義定中檔定設在接直,面介何任作實不以可 的您,中 Advices 在 Spring 2.0 。性植移可的間之式程用應 Java 的同不在別類作實 AOP 加增以,化準標面介作實 的 AOP ) – http://openhome.cc 良信林(冊手術技 Spring 2.0
  17. 17. 4 17 。定設成完可即 Annotation 的當適記標上 Advice 在要只,定設的瑣繁作中件文 XML 在用不是 處 好,作 運 以 可 才 本 版 的 上 以 JDK 5.0 在須必式方種這以所, Annotation 到用使於由,援支 Annotation 的 @AspectJ 用使是種三第 。面介的定特作實用不 且而Advice , 多許潔 簡 式 方 種 一 第 比 會上 定 設 在 , 籤 標 < aop> 的新 Spring 2.0 用使並 ,定設 的 XML Schema XML 於基 用 使 須 必 您 , 定 設 的 於 基 是 種 二 第 Chapter 4 Spring AOP
  18. 18. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 4.2 Advices ,別類個一是就說來體具中 在,輯邏正真的 Advices 了作 實 Aspect Java 由。) 多許理管 中集來別類個一由(法 方個一為 計設的度粒細 更或 Advices 是像, 的同不種幾了供提 Targets ,同不機時的 至合縫於 S pring Advices 小個這在 。 Before Advice 、 、 A fter Advice、 A round Advice T hrow Advice 。 識認始開 來 用使、寫 撰從以可您, 中節 Advices Spring AOP 4.2.1 Before Advice 現實以可您,叫呼被前之行執法方的件物標目在會 Before Advice 作實來 面介 org.springframework.aop.MethodBeforeAdvice Before Advice :示所 下如義定 的面介該,輯 邏的 package org.springframework.aop; public interface MethodBeforeAdvice extends BeforeAdvice { void before(Method method, Object[] args, Object target) throws Throwable; } ,面 介 自承繼 ,到看以可中義定在 M ethodBeforeAdvice BeforeAdvice (面 介 籤 標 是 都 者 兩 後 , 面 介 BeforeAdvice 自承繼又面介 Advice 而 T ag 承繼 interface ,法方 何 任 義 定 無 而 示 標 作 用 是 只, ) M ethodBeforeAdvice 執法方的定指所) (件物標目在會法方 BeforeAdvice b efore() , 了 T arget ,件物標目及數引、例實 的行執被得取以可您,行執被前之行 M ethod before() 之畢完行執法方 在,果 結 的 何 任 回 傳 不 以 所 , 為 告 宣 上 法 方 void before() 。 行 執 被 會 就法方 的 上 件 物 標 目 則 否,外 例 出 丟 您 非 除 , 後 的作實須必件物標目義定先首, 用使 何 如 範 示 來 例 實 以 Before Advice :面介4 18
  19. 19. Chapter 4 Spring AOP BeforeAdviceDemo IHello.javapackage onlyfun.caterpillar;public interface IHello { public void hello(String name);} 個一義定著接 HelloSpeaker 現實其讓,別類 IHello :面介 BeforeAdviceDemo HelloSpeaker.javapackage onlyfun.caterpillar;public class HelloSpeaker implements IHello { public void hello(String name) { System.out.println("Hello, " + name); }}, 下 況 情 的 改 修 何 任 行進它 對 不 在 , 畢 完 寫 撰 經 已 HelloSpeaker 在現到拿您是這下一像想,息訊些一錄記以可,前之行執法方 hello() 在要想您作實以可您。務服的誌日些一加增它對想但,碼始原有沒您,件組個一的MethodBeforeAdvice :如例,面介 BeforeAdviceDemo LogBeforeAdvice.javapackage onlyfun.caterpillar;import java.lang.reflect.Method;import java.util.logging.Level;import java.util.logging.Logger;import org.springframework.aop.MethodBeforeAdvice;public class LogBeforeAdvice implements MethodBeforeAdvice { private Logger logger = Logger.getLogger(this.getClass().getName()); 4 1
  20. 20. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) public void before(Method method, Object[] args, Object target) throws Throwable { logger.log(Level.INFO, "method starts..." + method); } } ,碼式程的訊資錄記些一了入加您,中作實的法方 before() 在 的要需給務服供提以可,務服的立獨個一為計設被別類 LogBeforeAdvice : 義 定 下 如 中 檔義定 在 要 只 著 接 , 件 物 BeforeAdviceDemo beans-config.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="logBeforeAdvice" class="onlyfun.caterpillar.LogBeforeAdvice"/> <bean id="helloSpeaker" class="onlyfun.caterpillar.HelloSpeaker"/> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="onlyfun.caterpillar.IHello"/> <property name="target" ref="helloSpeaker"/> <property name="interceptorNames"> <list> <value>logBeforeAdvice</value> </list> </property> </bean> </beans>4 2
  21. 21. Chapter 4 Spring AOP了用使還您,外之例實件物的 及 Advice 立建了除到意注 Target會別類個這,org.springframework.aop.framework.ProxyFactoryBean前 下一憶 回 ( 件 物 理 代 立 建 來 用 BeanFactory 是或 ApplicationContext 被物理代立建要需而因,現實來制機理代過透是要主 S pring AOP ,節小個一在,面介的用運可時理代定設上性屬 "proxyInterfaces" 在要您,)件,例實"target" 定設上 Target 在,件物 定設上 "interceptorNames" Advice定 有 所 上 面 介 至) (合 縫 被 會 ,時 法 方 標 目 定 指 不 在 B efore Advice W eave 。前之法方的義 :作運的 下 一 試測式 程 的 下 以 寫 撰 以 可 Before Advice BeforeAdviceDemo SpringAOPDemo.javapackage onlyfun.caterpillar;import org.springframework.context.ApplicationContext;import org.springframework.context. support.ClassPathXmlApplicationContext;public class SpringAOPDemo { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans-config.xml"); IHello helloProxy = (IHello) context.getBean("helloProxy"); helloProxy.hello("Justin"); }}為 面 介 作 操 換 轉 須 必,時 件 物 理 代 的 回 取 作 操 在 得 記 IHello 來,面 介 : 果 結行執 的 式 程 個 這 下 一 看 4 21
  22. 22. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 圖 4.4 BeforeAdviceDemo 果結行執的案專 與 的計設所您,到看以可中例範個這在 HelloSpeaker LogBeforeAdvice 道知用不它,說來 於對,件物的立獨個兩是 HelloSpeaker LogBeforeAdvice 在寫撰 的關相 與 何任有 沒 是 就 也 ( 在 存 的 LogBeforeAdvice API Hello- ,上之件物的它其至用運以可也 Speaker LogBeforeAdvice 而,)中 H ello- Speaker 。 計 設 的用 使 複 重 以 可 是 都 LogBeforeAdvice 與 的用 使 複 重 可 計 設 , 識 辨 的 AOP 於重著,神精的 出看以可 Aspects Advices。 件 物 的 用 使 複 重可計 設 , 識 辨 的 件 物 視 重 如 就 , OOP 將一逐是您果如 .jar 將得記,話的中之理管案專至入加案檔 spring-core.jar s pring-beans.jar s pring-context.jar spring-aop.jar 、 、 、 與 commons-logging.jar 。 入 加案 檔等 Classpath 4.2.2 After Advice After Advice 現 實 以 可 您,叫 呼 被 後 之 行 執 法 方 標 目 在 會 org.spring- ,輯邏的 framework.aop.AfterReturningAdvice作實來面介 After Advice AfterReturningAdvice :下如義定的面介 package org.springframework.aop; public interface AfterReturningAdvice extends Advice { void afterReturning(Object returnValue, Method m,4 22
  23. 23. Chapter 4 Spring AOP Object[] args, Object target) throws Throwable;}當 ,面介 自承繼接直 AfterReturningAdvice Advice a fterReturning(),件物標目與、數引、例實法方、值傳回的法方標目有數引的入傳中例出丟,程流式程用應的來下接止中要若, 回傳法方afterReturning() void 。式方的一唯是外方 的 為,中當子例的紹介中 在以可 B efore Advice H elloSpeaker hello() 個一義定先首, 上加 , 後 之 行 執 法 AfterReturningAdvice LogAfterAdvice :面介 作實來別類 AfterReturningAdvice AfterAdviceDemo LogAfterAdvice.javapackage onlyfun.caterpillar;import java.lang.reflect.Method;import java.util.logging.Level;import java.util.logging.Logger;import org.springframework.aop.AfterReturningAdvice;public class LogAfterAdvice implements AfterReturningAdvice { private Logger logger = Logger.getLogger(this.getClass().getName()); public void afterReturning(Object object, Method method, Object[] args, Object target) throws Throwable { logger.log(Level.INFO, "method ends..." + method); }} 在要只著接 beans-config.xml 加增中 After Advice 在及以,例實的的中ProxyFactoryBean "interceptorNames" 對加增 參的 LogAfterAdvice:下 如 寫 撰 檔 義 定 , 考 4 23
  24. 24. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) AfterAdviceDemo beans-config.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="logBeforeAdvice" class="onlyfun.caterpillar.LogBeforeAdvice"/> <bean id="logAfterAdvice" class="onlyfun.caterpillar.LogAfterAdvice"/> <bean id="helloSpeaker" class="onlyfun.caterpillar.HelloSpeaker"/> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="onlyfun.caterpillar.IHello"/> <property name="target" ref="helloSpeaker"/> <property name="interceptorNames"> <list> <value>logBeforeAdvice</value> <value>logAfterAdvice</value> </list> </property> </bean> </beans> 的定設前之了除,中義定在 LogBeforeAdvice 了入加還,外之 與式程的它其,務服誌日的 LogAfterAdvice 相案專 BeforeAdviceDemo : 示 所 下 如 面 畫考參 個 一 的 時 行 執 , 同4 24
  25. 25. Chapter 4 Spring AOP 圖 4.5 AfterAdviceDemo 果結行執的案專 個一計設以可也您 LogAspect 現實時同它讓,別類 Method- 與 BeforeAdvice 了為例範的節本,面介 AfterReturningAdvice 將而因,作實的面介調強 Advice 。計設開分4.2.3 Around Advice標目在何如道知經已您,中紹介的 Before Advice 與 After Advice 在法 方在要 您 果 如 上 實 事 , 輯 邏 務 服 的 入 介後、 前 行 執 法 方 的 件 物 Advices 作實過透接直以可您,輯邏務服的 Advices 入加後前行執 org.aopalliance.,務服 的 關 相 行 執 後 、 前行 執 法 方 於 , 面 介intercept.MethodInterceptor的面介 , Before Advice 與 供提別分用不而 After Advice M ethodInterceptor :下如義定package org.aopalliance.intercept;public interface MethodInterceptor { public Object invoke( MethodInvocation methodInvocation) throws Throwable;} 是稱名件套的 到意注 MethodInterceptor org.aopalliance.intercept ,作實示表這,訂制所 由是面介個這知得以可 AOP Alliance MethodInter-的範規ceptor 守遵於容相以可將,別類的面介 AOP Alliance AOP 。架框 4 2
  26. 26. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 在,是的同不 Before Advice及 與 After Advice MethodInterceptor 的 invoke() 用使否是定決行自要您,中法方 org.aopalliance.intercept. 會 。法方的件物標目行執來法方 MethodInvocation 的proceed() p roceed() 會機有您,前之束結 在以所,果結行執 Object 的後行執法方傳回 invoke() 正真在有只,的然當,件物的干相不全完個一另傳回是或,件物個這改修 。做麼 這 會 才 候 時 的 要 必 的前之在接直以可, 作 實何 如看 看來 際 實 MethodInterceptor AfterAdvice- Demo :寫 撰行 進 案 專 AroundAdviceDemo LogInterceptor.java package onlyfun.caterpillar; import java.util.logging.Level; import java.util.logging.Logger; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class LogInterceptor implements MethodInterceptor { private Logger logger = Logger.getLogger(this.getClass().getName()); public Object invoke(MethodInvocation methodInvocation) throws Throwable { logger.log(Level.INFO, "method starts..." + methodInvocation.getMethod()); Object result = null; try { result = methodInvocation.proceed(); } finally { logger.log(Level.INFO, "method ends..." + methodInvocation.getMethod() + "n"); }4 26
  27. 27. Chapter 4 Spring AOP return result; }} 個這用以可 Interceptor 的中案專 代取來 AfterAdviceDemo LogBefore-Advice 與 LogAfterAdvice :示所下如式方寫撰的檔義定 , B ean AroundAdviceDemo beans-config.xml<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="logInterceptor" class="onlyfun.caterpillar.LogInterceptor"/> <bean id="helloSpeaker" class="onlyfun.caterpillar.HelloSpeaker"/> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="onlyfun.caterpillar.IHello"/> <property name="target" ref="helloSpeaker"/> <property name="interceptorNames"> <list> <value>logInterceptor</value> </list> </property> </bean></beans> 與果結行執 AfterAdviceDemo 圖考參以可,的樣一是果結行執的案專4.5 。面畫的 4 27
  28. 28. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) Spring 入插先會,前法方個某行執正真在 Interceptor 個多有果如, Interceptor 行執後然,理處的己自行執會 I nterceptor 個每, M ethodInvocation 的 個一下有沒果如, proceed() 個一下給轉程流行執將這,法方 Interceptor Interceptor回返層一層一再,後畢完行執法方,法方的叫呼正真行執就, Interceptor 。 程 流 的 身 本式程 用 應 回 返 疊 堆 開 離 後 最 , 疊 堆 4.2.4 Throw Advice 用使以可您,事些某作件物務服些某知通時生發外例在要想若 Throws Advice 作實須必, Spring 作實要想中 在, Throws Advice org.springframe- 它,法方的何任義定有沒並面介個這而然,面介 work.aop.ThrowsAdvice 方 義 定 中 當 在 以 可 您 ,) (面 介 籤 標 個 一 是 只 T ag interface afterThrowing : 式 形 的下以 是 它 要 只 , 稱 名 法 afterThrowing([Method], [args], [target], subclassOfThrowable); 略省以可是示表等 與 、 [] 如例,定設的中 號括方Method a rgs target 是須必數參個這是就也, 是的要定一中法方,的 subclassOfThrowable 中 Throwable的 定 設 所驗檢 會 , 時 生 發 外 例 在 , 別 類 子 的 Throws Advice 法方個兩是下以,行執它知通就話的有果如,法方的型類外例合符有否是 :子例的告宣 void afterThrowing(Throwable throwable); void afterThrowing(Method method, Object[] args, Object target, Throwable throwable); 不的型類生發外例依則,態型 的同不告宣果如上法方在 Throwable 有告宣知通會 如例,法方的同不知通會,同 SomeException SomeException 。法方的 有告宣知通會 而,法方的數參 OtherException OtherException4 28
  29. 29. Chapter 4 Spring AOP您,法 方 的 應 對 行 執 是 只 務 任 的 ,時 生 發 外 例 當 到 意 注 T hrow Advice,後畢完行執 Throws Advice在,掉理處外例將中 在能不並 Throw Advice的式 程 用 應 入 介 不 並 ,中之式程用應至播傳被仍外例的先原 T hrow Advice 在要 想 果 如 , 的 責 負要所 身 本 式 程 用 應 是 舊仍理 處 外 例 , 理 處 外 例 Throw 。 外 例 的 它 其 出 丟 是法作 , 程 流 理 處 的 式 程 用 應 止 中 時 理 處Advice :面介 義定 先 首 , 子 例 際 實 的 Throws Advice 個看來 IHello ThrowAdviceDemo IHello.javapackage onlyfun.caterpillar;public interface IHello { public void hello(String name) throws Throwable;}作實來別類 個一義定著接 HelloSpeaker IHello 在並,面介 hello() 方 : 出 丟 外 例 的 時 誤錯生 發 式 程 擬 模 中 當 法 ThrowAdviceDemo HelloSpeaker.javapackage onlyfun.caterpillar;public class HelloSpeaker implements IHello { public void hello(String name) throws Throwable { System.out.println("Hello, " + name); // 外例生發!誤錯式程!歉抱 XD throw new Exception(" 外例生發 ..."); }}入 介 , 時 外 例 出 丟式程 用 應 在 要 需 您 果 如 服些一供提 Throw Advice 作 實 以 可 則 , 訊 資外例 些 一 錄 記 如 例 , 務 ThrowAdvice :面介 4 2
  30. 30. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) ThrowAdviceDemo SomeThrowAdvice.java package onlyfun.caterpillar; import java.lang.reflect.Method; import java.util.logging.Level; import java.util.logging.Logger; import org.springframework.aop.ThrowsAdvice; public class SomeThrowAdvice implements ThrowsAdvice { private Logger logger = Logger.getLogger(this.getClass().getName()); public void afterThrowing(Method method, Object[] args, Object target, Throwable subclass) { // 外例錄記 logger.log(Level.INFO, "Logging that a " + subclass + "Exception was thrown in " + method); } } 讓,義定的下以下寫中檔義定 在著接 Bean Throw Advice 生發外例在 :務服誌日供提時 ThrowAdviceDemo beans-config.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="someThrowAdvice" class="onlyfun.caterpillar.SomeThrowAdvice"/> <bean id="helloSpeaker" class="onlyfun.caterpillar.HelloSpeaker"/> <bean id="helloProxy"4 3
  31. 31. Chapter 4 Spring AOP class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="onlyfun.caterpillar.IHello"/> <property name="target" ref="helloSpeaker"/> <property name="interceptorNames"> <list> <value>someThrowAdvice</value> </list> </property> </bean></beans> 下 一 試 測來式 程 的 下 以 寫 撰 以 可 Throw Advice :作運般期預如否是 ThrowAdviceDemo SpringAOPDemo.javapackage onlyfun.caterpillar;import org.springframework.context.ApplicationContext;import org.springframework.context. support.ClassPathXmlApplicationContext;public class SpringAOPDemo { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans-config.xml"); IHello helloProxy = (IHello) context.getBean("helloProxy"); try { helloProxy.hello("Justin"); } catch(Throwable throwable) { // 理處外例的式程用應 System.err.println(throwable); } }} 4 31
  32. 32. 4 32 果結行執的案專 4.6 ThrowAdviceDemo 圖 :面畫 考 參 的 時 行 執 個 一看看來,務服誌日的外額供提 T hrow Advice ,輯 邏 的 外 例 理 處 式 程 用 應 入介不 T hrow Advice ,輯 邏 的 理 處 外 例 了 義 定 身 本 式 程 用 應,中 式 程 在 ) – http://openhome.cc 良信林(冊手術技 Spring 2.0
  33. 33. Chapter 4 Spring AOP4.3 Pointcut、Advisor行執面介的理代至合縫接直是都 的義定所,中節小個一前在 Advice的部細更義定以可還上實事,時生發外例中程過法方行執在者或,後、前在。)機時用應的 ( 的趣興感了義定 P ointcut 。機時合縫 Jointpoint A dvice, 合結體具,例實Spring 供提 用使,中 PointcutAdvisor Pointcut AdviceSpring 。 的應對有都 Pointcut 的建內 PointcutAdvisor4.3.1 NameMatchMethodPointcutAdvisor 了義定 Pointcut Jointpoint 在, Spring 用使中 PointcutAdvisor 供提來, 合結、Pointcut Advice P ointcutAdvisor 為 Advisor ,面介子的 A dvisor :下如義定的於面介package org.springframework.aop;import org.aopalliance.aop.Advice;public interface Advisor { boolean isPerInstance(); Advice getAdvice();} PointcutAdvisor 於面介 Spring :下如義定的中package org.springframework.aop;public interface PointcutAdvisor extends Advisor { Pointcut getPointcut();}的建內中Spring Pointcut的應對有都 PointcutAdvisor 介 來 先 邊 這 在, 用使何如,下一紹 Spring 的供提所 org.springframework.aop.support. 4 33
  34. 34. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 用, 的本基最是這, NameMatchMethodPointcutAdvisor PointcutAdvisor 定指) (式示表用使可,例 實 Spring 態靜中 Pointcut 供提以 e xpression 表 如例,定指來 用是者或,稱名法方之上標目的用應要所 Advice * hello* 的定指用應會都,時稱名法方的頭開為作 hello 以上件物理代行執示 。)法方的理代有所至用套被會 Advices ,子例的前之題主個這在( A dvice :面介的 了 義 定 您 設 假,說 來 子 例 的 際 實 個 舉 IHello NameMatchDemo IHello.java package onlyfun.caterpillar; public interface IHello { public void helloNewbie(String name); public void helloMaster(String name); } 義定著接 HelloSpeaker 作實來別類 IHello :面介 NameMatchDemo HelloSpeaker.java package onlyfun.caterpillar; public class HelloSpeaker implements IHello { public void helloNewbie(String name) { System.out.println("Hello, " + name + " newbie!"); } public void helloMaster(String name) { System.out.println("Hello, " + name + " master!"); } } 到用使會邊這如例, 的單簡 個 一 寫 撰 以 可 著 接 Advice BeforeAdvice- Demo 考參請,限有幅篇於基, LogBeforeAdvice 的中案專 4.2.1 的中 。 碼 式 程 出 列複重 再 不 邊 這 , 寫 撰 之 別 類 LogBeforeAdvice4 34
  35. 35. Chapter 4 Spring AOP 用使,檔義定 的下以寫撰著接 Bean NameMatchMethodPointcut- :起一在合結Advisor 將並,例實 Pointcut 供提 Advice NameMatchDemo beans-config.xml<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="logBeforeAdvice" class="onlyfun.caterpillar.LogBeforeAdvice"/> <bean id="helloAdvisor" class="org.springframework.aop. → support.NameMatchMethodPointcutAdvisor"> <property name="mappedName" value="*Newbie"/> <property name="advice" ref="logBeforeAdvice"/> </bean> <bean id="helloSpeaker" class="onlyfun.caterpillar.HelloSpeaker"/> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="onlyfun.caterpillar.IHello"/> <property name="target" ref="helloSpeaker"/> <property name="interceptorNames"> <list> <value>helloAdvisor</value> </list> </property> </bean></beans> 在 NameMatchMethodPointcutAdvisor 由,上性屬 "mappedName" 的了定指於 "*Newbie" 行 執 以 所, 合 符 稱 名 法 方 於 由,時 法 方 helloNewbie() 4 3
  36. 36. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 程的下以寫撰以可,輯邏務服的 "*Newbie" 用應會就, " logBeforeAdvice" : 期 預 合 符 否 是 果結看 看 , 試 測 行 進 來 式 NameMatchDemo SpringAOPDemo.java package onlyfun.caterpillar; import org.springframework.context.ApplicationContext; import org.springframework.context. support.ClassPathXmlApplicationContext; public class SpringAOPDemo { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans-config.xml"); IHello helloProxy = (IHello) context.getBean("helloProxy"); helloProxy.helloNewbie("Justin"); helloProxy.helloMaster("caterpillar"); } } : 示 所 下 如 面 畫考參 果 結 個 一 的 時 行 執 圖 4.7 NameMatchDemo 果結行執的案專 用使,時 義定在以可也您 Advisor 個多行進性屬 "mappedNames" Pointcut 改修可如例,義定式示表 beans-config.xml :容內的下以為4 36
  37. 37. Chapter 4 Spring AOP<beans ...> .... <bean id="helloAdvisor" class="org.springframework.aop. → support.NameMatchMethodPointcutAdvisor"> <property name="mappedNames"> <list> <value>helloNewbie</value> <value>helloMaster</value> </list> </property> <property name="advice" ref="logBeforeAdvice"/> </bean> ....</beans>4.3.2 RegExpMethodPointcutAdvisor Spring 的供提 org.springframework.aop.support.RegexpMethod-寫撰來PointcutAdvisor 用使您讓以可 Regular expression Pointcut 示表 合符在,例實的 Spring 態靜中 供提以用,式 Pointcut Regular expression : 號 符 個幾的 下 以 用 使 以 可 您 , Advices 用應下況情的 4.1 RegExpMethodPointcutAdvisor號符的用可時義定 表號符 述描. 元字一單何任合符+ 次多或次一元字個一前合符* 次多或次零元字個一前合符 Escape 何任 Regular expression 號符的到用使 4 37
  38. 38. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 的合 符 要 所 定 指 您 讓 性 屬 的 RegexpMethodPointcutAdvisor "pattern" 合符求要若如例,稱名法方加)稱名件套括包(稱名別類整完 :寫 撰 下 如 要 則 , 稱 名 法 方 的 始 開 的 下 onlyfun.caterpillar.IHello hello onlyfun.caterpillar.IHello.hello.* 符 定指要中式示表以所,用使 . 被經已號符 於由 Regular expression . 名 法方對 針 算 打 只 果 如 , 式 方 的 用 使 是 就 也 , ) E scape (脫跳要則,號 . :寫 撰 麼 這 以 可 則 , 稱名件 套 管 不 而 , 對 比 稱 .*hello.* 與別 類 的 用 使 所 中 案 專 用使以可 NameMatchDemo Advice一改要只, Bean :如例,了以可就檔義定 下 RegexpMatchDemo beans-config.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="logBeforeAdvice" class="onlyfun.caterpillar.LogBeforeAdvice"/> <bean id="regExpAdvisor" class="org.springframework.aop. → support.RegexpMethodPointcutAdvisor"> <property name="pattern" value=".*Newbie"/> <property name="advice" ref="logBeforeAdvice"/> </bean> <bean id="helloSpeaker" class="onlyfun.caterpillar.HelloSpeaker"/> <bean id="helloProxy"4 38
  39. 39. Chapter 4 Spring AOP class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="onlyfun.caterpillar.IHello"/> <property name="target" ref="helloSpeaker"/> <property name="interceptorNames"> <list> <value>regExpAdvisor</value> </list> </property> </bean></beans> 用應要法方的尾結 為稱名法方合符定設,中義定的面上在 NewbieAdvice 與 果 結 行 執 以 所 , 稱 名 別 類 、 件 套 的 面 前 其 論 無 且, NameMatch-Demo 。的樣一是果結行執的案專4.3.3 ControlFlowPointcut所 是 org.springframework.aop.support.ControlFlowPointcut Sping,中法方某的別類定指個某,中疊堆行執的法方在斷判為用作,別類的供提定確會才期時行執在是這於由,作動個某行執件物標目的您求要經曾否是 。能功Advices 態動的供提 是以所, Spring 入介否是 Pointcut為別類 的中 以 NameMatchMethodPointcutAdvisor LogBeforeAdvice要中法 方 個 某 在 否 是 , 中 別 類 在道知要想您,例 onlyfun.caterpillar.Some 入介則,話的有果如,作動些某行執件物標目的定指過求 LogBefore-Advice :寫撰下如檔義定 將以可,務服誌日供提來 Bean ControlFlowDemo beans-config.xml<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans 4 3
  40. 40. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="some" class="onlyfun.caterpillar.Some"/> <bean id="logBeforeAdvice" class="onlyfun.caterpillar.LogBeforeAdvice"/> <bean id="helloFlowControlPointcut" class="org.springframework.aop.support.ControlFlowPointcut"> <constructor-arg value="onlyfun.caterpillar.Some"/> </bean> <bean id="helloAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="logBeforeAdvice"/> <property name="pointcut" ref="helloFlowControlPointcut"/> </bean> <bean id="helloSpeaker" class="onlyfun.caterpillar.HelloSpeaker"/> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="onlyfun.caterpillar.IHello"/> <property name="target" ref="helloSpeaker"/> <property name="interceptorNames"> <list> <value>helloAdvisor</value> </list> </property> </bean> </beans> ,別類 了定指,時構建 在 ControlFlowPointcut onlyfun.caterpillar.Some 是就也(件物標目的定指了求要法方個某的中別類 Some 在若示表 ( 用應則,作動些某行執)例實 "helloSpeaker" Before Advice l ogBefore- Advice :寫撰下如別類 ,務服的誌日供提) S ome4 4
  41. 41. Chapter 4 Spring AOP ControlFlowDemo Some.javapackage onlyfun.caterpillar;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;public class Some implements ApplicationContextAware { private IHello helloProxy; public void setApplicationContext( ApplicationContext context) throws BeansException { helloProxy = (IHello) context.getBean("helloProxy"); } public void helloEverybody() { helloProxy.helloNewbie("Justin"); helloProxy.helloMaster("caterpillar"); } public void hello() { System.out.println("Hello!"); }} 得取便方了為ApplicationContext 得 獲以 helloSpeaker ,件物理代的Some 了現實別類 org.springframework.context.ApplicationContextAware下一試測來式程的單簡個一寫撰以可著接,面介 ControlFlowPointcut 運的 :示所下如,作 ControlFlowDemo SpringAOPDemo.javapackage onlyfun.caterpillar;import org.springframework.context.ApplicationContext;import org.springframework.context. support.ClassPathXmlApplicationContext;public class SpringAOPDemo { 4 41
  42. 42. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans-config.xml"); Some some = (Some) context.getBean("some"); if(args.length > 0 && "run".equals(args[0])) { some.helloEverybody(); } else { some.hello(); } } } 與都, 式 程 的 出 列 未 餘 其 NameMatchDemo 邊 這, 同 相 式 程 的 中 案 專 考參以可容內式程的整完,出列再不就 下一看來,案專 ControlFlowDemo 。果結的行執 訊字文的 現 出會 只 則 , 數 引 供提 有 沒 時 式 程 行 執 果 如 "run" "Hello!" 不並中疊堆行執在, Some 的例實 行執有沒為因是這,息 helloEverybody() 某行執例實 求要曾法方某的別類 :義定的定指所合符 S ome " helloSpeaker" 。作動些 的別類 行執會則,數引 了供提時式程行執果如 "run" Some 行執件物理代的 helloEverybody() 求要中法方,法方 "helloSpeaker" 因, 容 內 的 定 指 中 檔 義 定 合 符 , 法 方 helloNewbie() helloMaster() 與 Bean :示所 下 如 果 結 的 行 執 個一 , 息 訊 務 服 供 提 來 LogBeforeAdvice 用應會而4 42
  43. 43. 4 43 數引的時行執定指中 Eclipse 在 4.9 圖 :如例,數引入輸中框字文」 arguments P rogram 「在,籤 頁」 A rguments 「擇 選 後 然,令 指」 R un/Run... 「 的上單選 Eclipse 行執以可,數引的時行執定指要中 Eclipse 在 。 Pointcut 態 靜 用 使 量儘, 下 況 情 的 能 可 在 議建此 因 , 遲 延 能 效 的 倍 10 5 JDK 到 有 會 能 可 上 的同不 在 , 慢 很 會 時 行 執以所 , 行 進 期 時 行 執 在 是斷 判 的 疊 堆 行 執 於 由,出 付 的 上 能 效 於 在 是 就 題 問 的 態動 Pointcut 果結行執的案專 4.8 ControlFlowDemo 圖 Chapter 4 Spring AOP
  44. 44. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 4.3.4 Pointcut 介面 的 Spring Pointcut 作實過透是 org.springframework.aop.Pointcut 面介 :下 如 義 定 其 , 現 實 來 package org.springframework.aop; public interface Pointcut { ClassFilter getClassFilter(); MethodMatcher getMethodMatcher(); Pointcut TRUE = TruePointcut.INSTANCE; } Pointcut.TRUE 是 的回傳它,作實單簡的面介 Pointcut 是 ClassFilter ClassFilter.TRUE 。 回傳 是 的回傳而, MethodMatcher MethodMatcher.TRUE ClassFilter :示所下如義定其, 用應要否是別類個一定決面介 Advice package org.springframework.aop; public interface ClassFilter { boolean matches(Class clazz); ClassFilter TRUE = TrueClassFilter.INSTANCE; } matches() ,義定的 合符是不是別類的入傳定決要中法方 Pointcut ClassFilter.TRUE總法方 的它,作實單簡的面介 ClassFilter 是 matches() 回傳是 true 這 用使以 可 則 , 稱 名 法 方 到 慮 考 只 Pointcut的立建要想果如, 。法方個 而 MethodMatcher 用應要否是法方個某 定決 Advice :示所下如義定其, package org.springframework.aop; import java.lang.reflect.Method;4 44
  45. 45. Chapter 4 Spring AOPpublic interface MethodMatcher { boolean matches(Method method, Class targetClass); boolean isRuntime(); boolean matches(Method method, Class targetClass, Object[] args); MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;} matches() 合符否 是 法 方 個 某 的 別 類 個 某 定 決 法 方 Pointcut 兩有,義定 是像, 態 靜 於 用使本 版 個 一 第 , 本 版 個 Pointcut NameMatchMethodPoint-, 行執被 會 是 總 法 方 個 一 第 ,cutAdvisor R egExpMethodPointcutAdvisor 、 個二第時此, 回傳會 Pointcut 則, isRuntime() 態靜是果如 false matches() 的本版個二第,時 為 在有只 , 行 執 被 會 不 法 方 isRuntime() true matches() 。 ControlFlowPointcut 如例,行執被會才版個 一 第 的 它 , 作 實 單 簡 的 MethodMatcher.TRUE 是 MethodMatcher態靜示表, 回傳是總 matches() , 回傳是總 true i sRuntime() 的本 false出丟會就則否,法方Pointcut 的本版個二第行執以可不以所, matches() 。外例UnsupportedOperationException4.3.5 Pointcut 交集、聯集操作 個幾有現發您,中之這在且並, 個多了立建果如 Pointcuts Pointcuts現對接直以可您,時義定的 個一另為成,起一在合組以可義定的 Pointcuts,作操的) (集聯、) Pointcuts (集交行進,件物 的在 I ntersection U nion的 是org.springframework.aop.support.ComposablePointcut Pointcut:作操個這成完來法方 、 的它作 操 以 可 , 別 類 作 實 intersection() u nion()ComposablePointcut intersection(ClassFilter filter);ComposablePointcut intersection(MethodMatcher mm)ComposablePointcut intersection(Pointcut other)ComposablePointcut union(ClassFilter filter) 4 4
  46. 46. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) ComposablePointcut union(MethodMatcher mm) :如例 Pointcut pc = new ComposablePointcut() .union(classFilter) .intersection(methodMatcher) .intersection(pointcut); 在 ComposablePointcut 個兩理 處 以 可 法 方 有 沒 中 Pointcut 您,集聯的 用使要 的 org.springframework.aop.support.Pointcuts union() :如 例,法方 Pointcut union = Pointcuts.union(pointcut1, pointcut2); 如,作操集聯或集交行進以可才寫撰接直中式程在須必是這,的然當 於 後 然 , 別 類 個 一 計設以 可 則 , 告 宣 接 直 中 檔 義 定 在 望 希 您 果 Bean Bean :如 例 , 性 用 重 的 作 操 加 增 以 可 這 , 例 實的別 類 該 告 宣 中 檔 義 定 Pointcut package onlyfun.caterpillar; import java.util.List; import org.springframework.aop.ClassFilter; import org.springframework.aop.MethodMatcher; import org.springframework.aop.Pointcut; import org.springframework.aop. framework.AopConfigException; import org.springframework.aop.support.Pointcuts; public class UnionPoint implements Pointcut { private Pointcut pointcut; public ClassFilter getClassFilter() { return getPointcut().getClassFilter(); } public MethodMatcher getMethodMatcher() { return getPointcut().getMethodMatcher();4 46
  47. 47. Chapter 4 Spring AOP } public void setPointcuts(List pointcuts) { if(pointcuts == null || pointcuts.size == 0) { throw new AopConfigException( "個一定設要少至 Pointcut"); } pointcut = (Pointcut) pointcuts.get(0); for(int i = 0; i < pointcuts.size(); i++) { Pointcut next = (Pointcut) pointcuts.get(i); pointcut = Pointcuts.union(pointcut, next); } } private Pointcut getPointcut() { if(pointcut == null) { throw new AopConfigExeption(" 定設有沒 Pointcut"); } return pointcut; }} 4 47
  48. 48. 4 48 。能功的常為以 習很是則,說來)式函(法方的作操可加增件物為態動對,員 人計設的 JavaScript 悉熟如例,員人計設的言語本腳態動悉熟 。 Introduction 現實來 framework.aop.IntroductionInterceptororg.spring-作實過透以可,中 Spring AOP 在上實事,議思可不得顯法方的作操可加增件物為態動,說來點觀的計設別類言語式程 就 Java 。 上 之 件 物 到 法方作 操 的 外 額 些 一 加 增以可 卻 , 下 況 情 的 案 檔別類之件物該改修不在,件物的好義定已個某讓如例,」) 法 方 的作 操 可了加增是就說來體具(責職的件物標目了加增接直,義定為行的件物標目了響影「它,看來度角的者用使從, Advice 的別特個是 Introduction 。 作 動 的 誌 日 些一了 加 增 乎 似 來 看 法 方 些 某 讓 如 例 , 」 為 行 的法 方 些 某 上 件 物 標 目 了 響 影「們 它 , 看 來 度 角 的 者 用 使 從 , Throw Advice、 A round Advice 、 A fter Advice 、 Before Advice 的過紹介前之於對 4.4.1 IntroductionInterceptor 。責職的有沒所先原) (入加態動 M ixin件物為,為行的作操可些一了多空憑件物像好就,為行的件物個整入介接直是而,務服入介後前法方在 等 、 Advice 像不 A fter Advice BeforeAdvice它,看來上為行從, 的殊特種一是 Advice ,中 在 I ntroduction Spring 4.4 Introduction ) – http://openhome.cc 良信林(冊手術技 Spring 2.0
  49. 49. Chapter 4 Spring AOP 與 IntroductionInterceptor 承繼 MethodInterceptor DynamicIntro- 自承繼(法方ductionAdvice 中其,面介 implementsInterface() Dynamic- 的前目示表,話的 回傳果如)IntroductionAdvice true IntroductionInterceptor用使要您時此,)面介的為行加增外額要是就也(面介的定規了作實用使可不您,為行的外額行執件物標目讓,法方的上面介行執invoke()的有沒 來 原 上 件 物 是 的 行 執 要 為 因 , 法 方MethodInvocation proceed() 的 proceed() 。義意有沒法方 行執,為行假,說來子例的際實個舉,象抽較比會 Introduction 解理來上字文從 : 別 類 的 下以有 經 已 中 統 系 的 您 設 IntroductionDemo ISome.javapackage onlyfun.caterpillar;public interface ISome { public void doSome();} IntroductionDemo Some.javapackage onlyfun.caterpillar;public class Some implements ISome { public void doSome() { System.out.println(" 。。。責職的件物來原 "); }}的作 操 可 些 一 加 增 別 類 為 , 下 況 情 的 案檔始 原 改 修 不 在 望 希 您 Some也的道知一唯,案檔 有只 , 有 沒 都 案 檔 碼 始原連 至 甚 您 許 也 , 法 方 .class可別類 望 希 , 下 況 情的改 修 出 做 們 它 對 不 在 , 明 說 的 們 它 是 許 API Some doOther() 。法方 加增以 4 4
  50. 50. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) 作實由藉以可,中 Spring 在 IntroductionInterceptor 面上成完來面介 :面介立建法方 為先首,務任的 doOther() IntroductionDemo IOther.java package onlyfun.caterpillar; public interface IOther { public void doOther(); } 個一義定著接 OtherIntroduction 作實時同別類 IntroductionInterceptor :如例,面介 與面介 IOther IntroductionDemo OtherIntroduction.java package onlyfun.caterpillar; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.IntroductionInterceptor; public class OtherIntroduction implements IntroductionInterceptor, IOther { // 自作實否是 IOther 面介 public boolean implementsInterface(Class clazz) { return clazz.isAssignableFrom(IOther.class); } public Object invoke(MethodInvocation methodInvocation) throws Throwable { // 自來法方的行執果如 IOther 義定的面介 if(implementsInterface( methodInvocation.getMethod().getDeclaringClass())) { // (入加外額行執 mixin為行的) return methodInvocation.getMethod(). invoke(this, methodInvocation.getArguments()); } else { return methodInvocation.proceed();4
  51. 51. Chapter 4 Spring AOP } } public void doOther() { System.out.println(" 。。。責職的加增 "); }} 在要著接 Bean 將中檔義定 Introduction 至合縫 Some 用 使, 上 之 件 物org.springframework.aop.support.DefaultIntroductionAdvisor 以可就:如例,了 IntroductionDemo beans-config.xml<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="some" class="onlyfun.caterpillar.Some"/> <bean id="otherIntroduction" class="onlyfun.caterpillar.OtherIntroduction"/> <bean id="otherAdvisor" class="org.springframework.aop. → support.DefaultIntroductionAdvisor"> <constructor-arg ref="otherIntroduction"/> <constructor-arg value="onlyfun.caterpillar.IOther"/> </bean> <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="onlyfun.caterpillar.ISome"/> <property name="target" ref="some"/> <property name="interceptorNames"> 4 1
  52. 52. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) <list> <value>otherAdvisor</value> </list> </property> </bean> </beans> 它給要需,時構建在 DefaultIntroductionAdvisor IntroductionInterceptor 測式程的單簡個一寫撰來,在現,面介的為行外額理代要所及以,例實的 :為 行 加 增 外 額 件 物 為謂何 解 了 步 一 進 更 以 可,中 當 式 程 個 這 從 , 試 IntroductionDemo SpringAOPDemo.java package onlyfun.caterpillar; import org.springframework.context.ApplicationContext; import org.springframework.context. support.ClassPathXmlApplicationContext; public class SpringAOPDemo { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans-config.xml"); ISome some = (ISome) context.getBean("proxyFactoryBean"); some.doSome(); //像好來看 some 責職了加增態動件物 ((IOther) some).doOther(); } }4 2

×