More Related Content
Similar to Spring 2.0 技術手冊第四章 - Spring AOP
Similar to Spring 2.0 技術手冊第四章 - Spring AOP(20)
Spring 2.0 技術手冊第四章 - Spring AOP
- 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. 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. 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. 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. 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. 4 6
。理原本基的理代解了您讓在是,的目
的理代態靜紹介邊這在,任勝法無就時大稍模規式程在理代態靜,理代行
進法方個每為要必勢,多很法方的理代要果如且而,件物的型類種一於務
服只面介個一的件物理代,的到看所您如而然,例範本基的理代態靜是這
程流作運的制機理代 4.2 圖
:程流作運的制機理
代出看步一進更來式方的解圖從以可,責職的它於心專以可 HelloSpeaker
,作動誌日入介必不時寫撰在 HelloSpeaker
得使這,作動的誌日上加後前
其在並,hello()
行執來 HelloSpeaker
的正真理代將 件物理代 HelloProxy
果結行執案專 4.1 StaticProxyDemo 圖
) – http://openhome.cc 良信林(冊手術技 Spring 2.0
- 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 4 17
。定設成完可即 Annotation
的當適記標上 Advice 在要只,定設的瑣繁作中件文 XML
在用不是
處 好,作 運 以 可 才 本 版 的 上 以 JDK 5.0
在須必式方種這以所, Annotation
到用使於由,援支 Annotation
的 @AspectJ
用使是種三第
。面介的定特作實用不 且而Advice
, 多許潔 簡 式 方 種 一 第 比 會上 定 設 在 , 籤 標 < aop>
的新 Spring 2.0
用使並
,定設 的 XML Schema XML
於基 用 使 須 必 您 , 定 設 的 於 基 是 種 二 第
Chapter 4 Spring AOP
- 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 4 32
果結行執的案專 4.6 ThrowAdviceDemo 圖
:面畫 考 參 的 時 行 執 個 一
看看來,務服誌日的外額供提 T hrow Advice
,輯 邏 的 外 例 理 處 式 程 用 應 入
介不 T hrow Advice
,輯 邏 的 理 處 外 例 了 義 定 身 本 式 程 用 應,中 式 程 在
) – http://openhome.cc 良信林(冊手術技 Spring 2.0
- 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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