Successfully reported this slideshow.
Your SlideShare is downloading. ×

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

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

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.java package 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.java package 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.java package onlyfun.caterpillar; public interface IHello { public void hello(String name); } 的輯邏務商現實讓後然 HelloSpeaker 現實別類 IHello :如例,面介 DynamicProxyDemo HelloSpeaker.java package 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.java package 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 cutting Cross- 出示表解圖下以用使可則,段片式程查檢全安、誌日的關相入 寫的生生硬被像中碼式程的件物,務服等查檢全安與誌日入加要了為在現 一之解圖 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.java package onlyfun.caterpillar; public interface IHello { public void hello(String name); } 個一義定著接 HelloSpeaker 現實其讓,別類 IHello :面介 BeforeAdviceDemo HelloSpeaker.java package onlyfun.caterpillar; public class HelloSpeaker implements IHello { public void hello(String name) { System.out.println("Hello, " + name); } } , 下 況 情 的 改 修 何 任 行進它 對 不 在 , 畢 完 寫 撰 經 已 HelloSpeaker 在現 到拿您是這下一像想,息訊些一錄記以可,前之行執法方 hello() 在要想您 作實以可您。務服的誌日些一加增它對想但,碼始原有沒您,件組個一的 MethodBeforeAdvice :如例,面介 BeforeAdviceDemo LogBeforeAdvice.java package 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.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.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.java package 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 OtherException 4 28
  29. 29. Chapter 4 Spring AOP 您,法 方 的 應 對 行 執 是 只 務 任 的 ,時 生 發 外 例 當 到 意 注 T hrow Advice ,後畢完行執 Throws Advice在,掉理處外例將中 在能不並 Throw Advice 的式 程 用 應 入 介 不 並 ,中之式程用應至播傳被仍外例的先原 T hrow Advice 在要 想 果 如 , 的 責 負要所 身 本 式 程 用 應 是 舊仍理 處 外 例 , 理 處 外 例 Throw 。 外 例 的 它 其 出 丟 是法作 , 程 流 理 處 的 式 程 用 應 止 中 時 理 處 Advice :面介 義定 先 首 , 子 例 際 實 的 Throws Advice 個看來 IHello ThrowAdviceDemo IHello.java package onlyfun.caterpillar; public interface IHello { public void hello(String name) throws Throwable; } 作實來別類 個一義定著接 HelloSpeaker IHello 在並,面介 hello() 方 : 出 丟 外 例 的 時 誤錯生 發 式 程 擬 模 中 當 法 ThrowAdviceDemo HelloSpeaker.java package 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.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"); 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 AOP 4.3 Pointcut、Advisor 行執面介的理代至合縫接直是都 的義定所,中節小個一前在 Advice 的部細更義定以可還上實事,時生發外例中程過法方行執在者或,後、前 在。)機時用應的 ( 的趣興感了義定 P ointcut 。機時合縫 Jointpoint A dvice , 合結體具,例實 Spring 供提 用使,中 PointcutAdvisor Pointcut Advice Spring 。 的應對有都 Pointcut 的建內 PointcutAdvisor 4.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 的中 。 碼 式 程 出 列複重 再 不 邊 這 , 寫 撰 之 別 類 LogBeforeAdvice 4 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> 用應要法方的尾結 為稱名法方合符定設,中義定的面上在 Newbie Advice 與 果 結 行 執 以 所 , 稱 名 別 類 、 件 套 的 面 前 其 論 無 且, 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 ome 4 4
  41. 41. Chapter 4 Spring AOP ControlFlowDemo Some.java package 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.java package 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 AOP public 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() 。外例 UnsupportedOperationException 4.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.IntroductionInterceptor org.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.java package onlyfun.caterpillar; public interface ISome { public void doSome(); } IntroductionDemo Some.java package 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
  53. 53. Chapter 4 Spring AOP 有會不並先原它,說來件物的考參所 於對 some doOther()操供可法方 在現,制機 Spring AOP的 過透而然,作 Introduction some 件物的考參所 : 果 結 的 行 執下一 看 來 以 可 , 作 操 以 可 法 方 doOther() 了多 圖 4.10 IntroductionDemo 果結行執的案專 4.4.2 DelegatingIntroductionInterceptor org.springframework.aop.support.DelegatingIntroductionInterceptor 可您, 別 類 作 實 的 供 提 所 面 介 Spring AOP 為中 IntroductionInterceptor 是 件物有帶以可並,為行的加增件物標目為望希加添,別類個這承繼接直以 ,態狀的定鎖」否「、」是「有帶攜件物讓如例,態狀的己自 D elegating- 。 節細的 份 部 大 了 作 實 經 已 IntroductionInterceptor :別類 的 樣 這 有 經 已 中 統系設 假 , 說 來 子 例 個 舉 DelegatingIntroductionDemo ISome.java package onlyfun.caterpillar; public interface ISome { public void setSome(String some); public String getSome(); } 4 3
  54. 54. Spring 2.0 良信林(冊手術技 – http://openhome.cc ) DelegatingIntroductionDemo Some.java package onlyfun.caterpillar; public class Some implements ISome { private String some; public void setSome(String some) { this.some = some; } public String getSome() { return some; } } 個 一 加 增 以 可 望希您 , 下 況 情 的 容 內 式 程 Some.java 改修不在 locked 定設來法方 boolean 與 的作操可加增並,員成料資態型 lock() 的 unlock() 定 鎖 則, 為 定 設 被 locked true false 果 如, 或 為 員 成 locked true setSome() 。) ( 動變可 不 為 定 鎖 件 物 將 是就也 , 行 執 被 法 無 法 方 I mmutable 的件物標目至加添想是的義定面上,面介 ILockable 個一義定先以可 :法方作操 DelegatingIntroductionDemo ILockable.java package onlyfun.caterpillar; public interface ILockable { public void lock(); public void unlock(); public boolean isLocked(); } 承繼 著接 DelegatingIntroductionInterceptor 作實時同並,別類 ILockable :面介 4 4

×