日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

使用Spring进行面向切面编程(AOP)---讲解+代码

發(fā)布時(shí)間:2024/9/27 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Spring进行面向切面编程(AOP)---讲解+代码 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

6.1. 簡(jiǎn)介

6.2.4.1. 前置通知(Before advice)

一個(gè)切面里使用 @Before 注解聲明前置通知:

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

@Aspect

public class BeforeExample {

???????? @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")

???????? public void doAccessCheck() { // ... }

}

如果使用一個(gè)in-place 的切入點(diǎn)表達(dá)式,我們可以把上面的例子換個(gè)寫法:

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

@Aspect

public class BeforeExample {

??????? @Before("execution(* com.xyz.myapp.dao.*.*(..))")

??????? public void doAccessCheck() { // ... }

}

6.2.4.2. 返回后通知(After returning advice)返回后通知通常在一個(gè)匹配的方法返回的時(shí)候執(zhí)行。使用 @AfterReturning 注解來聲明:

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.AfterReturning;

@Aspect

public class AfterReturningExample {

????????? @AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")

????????? public void doAccessCheck() { // ... }

}

說明:你可以在同一個(gè)切面里定義多個(gè)通知,或者其他成員。我們只是在展示如何定義一個(gè)簡(jiǎn)單的通知。這些例子主要的側(cè)重點(diǎn)是正在討論的問題。有時(shí)候你需要在通知體內(nèi)得到返回的值。你可以使用以 @AfterReturning 接口的形式來綁定返回值:

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.AfterReturning;

@Aspect

public class AfterReturningExample {

??????????@AfterReturning( pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()", returning="retVal")

????????? public void doAccessCheck(Object retVal) { // ... }

}

在 returning 屬性中使用的名字必須對(duì)應(yīng)于通知方法內(nèi)的一個(gè)參數(shù)名。 當(dāng)一個(gè)方法執(zhí)行返回后,返回值作為相應(yīng)的參數(shù)值傳入通知方法。 一個(gè) returning 子句也限制了只能匹配到返回指定類型值的方法。 (在本例子中,返回值是 Object 類,也就是說返回任意類型都會(huì)匹配)

6.2.4.3. 拋出后通知(After throwing advice)拋出后通知在一個(gè)方法拋出異常后執(zhí)行。使用 @AfterThrowing 注解來聲明:

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.AfterThrowing;

@Aspect

public class AfterThrowingExample {

????????? @AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")

????????? public void doRecoveryActions() { // ... }

}

你通常會(huì)想要限制通知只在某種特殊的異常被拋出的時(shí)候匹配,你還希望可以在通知體內(nèi)得到被拋出的異常。 使用 throwing 屬性不光可以限制匹配的異常類型(如果你不想限制,請(qǐng)使用 Throwable 作為異常類型),還可以將拋出的異常綁定到通知的一個(gè)參數(shù)上。

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.AfterThrowing;

@Aspect

public class AfterThrowingExample {

????????? @AfterThrowing( pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()", throwing="ex")

????????? public void doRecoveryActions(DataAccessException ex) { // ... }

}

在 throwing 屬性中使用的名字必須與通知方法內(nèi)的一個(gè)參數(shù)對(duì)應(yīng)。 當(dāng)一個(gè)方法因拋出一個(gè)異常而中止后,這個(gè)異常將會(huì)作為那個(gè)對(duì)應(yīng)的參數(shù)送至通知方法。 throwing 子句也限制了只能匹配到拋出指定異常類型的方法(上面的示例為 DataAccessException)。

6.2.4.4. 后通知(After (finally) advice)不論一個(gè)方法是如何結(jié)束的,在它結(jié)束后(finally)后通知(After (finally) advice)都會(huì)運(yùn)行。 使用 @After 注解來聲明。這個(gè)通知必須做好處理正常返回和異常返回兩種情況。通常用來釋放資源。

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.After;

@Aspect

public class AfterFinallyExample {

????????? @After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")

????????? public void doReleaseLock() { // ... }

}

6.2.4.5. 環(huán)繞通知(Around Advice)最后一種通知是環(huán)繞通知。環(huán)繞通知在一個(gè)方法執(zhí)行之前和之后執(zhí)行。 它使得通知有機(jī)會(huì)既在一個(gè)方法執(zhí)行之前又在執(zhí)行之后運(yùn)行。并且,它可以決定這個(gè)方法在什么時(shí)候執(zhí)行,如何執(zhí)行,甚至是否執(zhí)行。 環(huán)繞通知經(jīng)常在在某線程安全的環(huán)境下,你需要在一個(gè)方法執(zhí)行之前和之后共享某種狀態(tài)的時(shí)候使用。 請(qǐng)盡量使用最簡(jiǎn)單的滿足你需求的通知。(比如如果前置通知(before advice)也可以適用的情況下不要使用環(huán)繞通知)。環(huán)繞通知使用 @Around 注解來聲明。通知的第一個(gè)參數(shù)必須是 ProceedingJoinPoint 類型。 在通知體內(nèi),調(diào)用 ProceedingJoinPoint 的 proceed() 方法將會(huì)導(dǎo)致潛在的連接點(diǎn)方法執(zhí)行。 proceed 方法也可能會(huì)被調(diào)用并且傳入一個(gè) Object[] 對(duì)象-該數(shù)組將作為方法執(zhí)行時(shí)候的參數(shù)。當(dāng)傳入一個(gè) Object[] 對(duì)象的時(shí)候,處理的方法與通過AspectJ編譯器處理環(huán)繞通知略有不同。 對(duì)于使用傳統(tǒng)AspectJ語言寫的環(huán)繞通知來說,傳入?yún)?shù)的數(shù)量必須和傳遞給環(huán)繞通知的參數(shù)數(shù)量匹配(不是后臺(tái)的連接點(diǎn)接受的參數(shù)數(shù)量),并且特定順序的傳入?yún)?shù)代替了將要綁定給連接點(diǎn)的原始值(如果你看不懂不用擔(dān)心)。 Spring采用的方法更加簡(jiǎn)單并且更好得和他的基于代理(proxy-based),只匹配執(zhí)行的語法相適用。 如果你適用AspectJ的編譯器和編織器來編譯為Spring而寫的@AspectJ切面和處理參數(shù),你只需要了解這一區(qū)別即可。 有一種方法可以讓你寫出100%兼容Spring AOP和AspectJ的,我們將會(huì)在后續(xù)的通知參數(shù)(advice parameters)的章節(jié)中討論它。

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.ProceedingJoinPoint;

@Aspect

public class AroundExample {

????????? @Around("com.xyz.myapp.SystemArchitecture.businessService()")

????????? public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {

??????????????????? // start stopwatch

??????????????????? Object retVal = pjp.proceed();

??????????????????? // stop stopwatch

??????????????????? return retVal;

???????????}

}

方法的調(diào)用者得到的返回值就是環(huán)繞通知返回的值。 例如:一個(gè)簡(jiǎn)單的緩存切面,如果緩存中有值,就返回該值,否則調(diào)用proceed()方法。 請(qǐng)注意proceed可能在通知體內(nèi)部被調(diào)用一次,許多次,或者根本不被調(diào)用。

6.2.4.6. 通知參數(shù)(Advice parameters)Spring 2.0 提供了完整的通知類型 - 這意味著你可以在通知簽名中聲明所需的參數(shù),(就像在以前的例子中我們看到的返回值和拋出異常一樣)而不總是使用Object[]。 我們將會(huì)看到如何在通知體內(nèi)訪問參數(shù)和其他上下文相關(guān)的值。首先讓我們看以下如何編寫普通的通知以找出正在被通知的方法。

6.2.4.6.1. 訪問當(dāng)前的連接點(diǎn)任何通知方法可以將第一個(gè)參數(shù)定義為 org.aspectj.lang.JoinPoint 類型 (環(huán)繞通知需要定義為 ProceedingJoinPoint 類型的, 它是 JoinPoint 的一個(gè)子類。) JoinPoint 接口提供了一系列有用的方法, 比如 getArgs()(返回方法參數(shù))、getThis()(返回代理對(duì)象)、getTarget()(返回目標(biāo))、getSignature()(返回正在被通知的方法相關(guān)信息)和 toString()(打印出正在被通知的方法的有用信息)。

6.2.4.6.2. 傳遞參數(shù)給通知(Advice)我們已經(jīng)看到了如何綁定返回值或者異常(使用后置通知(after returning)和異常后通知(after throwing advice)。 為了可以在通知(adivce)體內(nèi)訪問參數(shù),你可以使用 args 來綁定。 如果在一個(gè)參數(shù)表達(dá)式中應(yīng)該使用類型名字的地方使用一個(gè)參數(shù)名字,那么當(dāng)通知執(zhí)行的時(shí)候?qū)?yīng)的參數(shù)值將會(huì)被傳遞進(jìn)來。 可能給出一個(gè)例子會(huì)更好理解。假使你想要通知(advise)接受某個(gè)Account對(duì)象作為第一個(gè)參數(shù)的DAO操作的執(zhí)行,你想要在通知體內(nèi)也能訪問到account對(duì)象,你可以寫如下的代碼:

@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &&" + "args(account,..)")

public void validateAccount(Account account) { // ...}

切入點(diǎn)表達(dá)式的 args(account,..) 部分有兩個(gè)目的: 首先它保證了只會(huì)匹配那些接受至少一個(gè)參數(shù)的方法的執(zhí)行,而且傳入的參數(shù)必須是 Account 類型的實(shí)例, 其次它使得可以在通知體內(nèi)通過 account 參數(shù)來訪問那個(gè)account參數(shù)。另外一個(gè)辦法是定義一個(gè)切入點(diǎn),這個(gè)切入點(diǎn)在匹配某個(gè)連接點(diǎn)的時(shí)候“提供”了一個(gè)Account對(duì)象, 然后直接從通知中訪問那個(gè)命名的切入點(diǎn)。你可以這樣寫:

@Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &&" + "args(account,..)")

private void accountDataAccessOperation(Account account) {}

@Before("accountDataAccessOperation(account)")

public void validateAccount(Account account) { // ..}如果想要知道更詳細(xì)的內(nèi)容,請(qǐng)參閱 AspectJ 編程指南。代理對(duì)象(this)、目標(biāo)對(duì)象(target) 和注解(@within, @target, @annotation, @args)都可以用一種簡(jiǎn)單格式綁定。 以下的例子展示了如何使用 @Auditable 注解來匹配方法執(zhí)行,并提取AuditCode。首先是 @Auditable 注解的定義:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface Auditable { AuditCode value();}

然后是匹配 @Auditable 方法執(zhí)行的通知:

@Before("com.xyz.lib.Pointcuts.anyPublicMethod() && " + "@annotation(auditable)")

public void audit(Auditable auditable) { AuditCode code = auditable.value(); // ...}

6.2.4.6.3. 決定參數(shù)名綁定在通知上的參數(shù)依賴切入點(diǎn)表達(dá)式的匹配名,并借此在(通知(advice)和切入點(diǎn)(pointcut))的方法簽名中聲明參數(shù)名。 參數(shù)名 無法 通過Java反射來獲取,所以Spring AOP使用如下的策略來決定參數(shù)名字:如果參數(shù)名字已經(jīng)被用戶明確指定,則使用指定的參數(shù)名: 通知(advice)和切入點(diǎn)(pointcut)注解有一個(gè)額外的"argNames"屬性,該屬性用來指定所注解的方法的參數(shù)名 - 這些參數(shù)名在運(yùn)行時(shí)是 可以 訪問的。例子如下:

@Before( value="com.xyz.lib.Pointcuts.anyPublicMethod() && " + "@annotation(auditable)", argNames="auditable")

public void audit(Auditable auditable) {

????????? AuditCode code = auditable.value(); // ...

}

如果一個(gè)@AspectJ切面已經(jīng)被AspectJ編譯器(ajc)編譯過了,那么就不需要再添加 argNames 參數(shù)了,因?yàn)榫幾g器會(huì)自動(dòng)完成這一工作。使用 'argNames' 屬性有點(diǎn)不那么優(yōu)雅,所以如果沒有指定'argNames' 屬性, Spring AOP 會(huì)尋找類的debug信息,并且嘗試從本地變量表(local variable table)中來決定參數(shù)名字。 只要編譯的時(shí)候使用了debug信息(至少要使用 '-g:vars' ),就可獲得這些信息。

使用這個(gè)flag編譯的結(jié)果是:

(1)你的代碼將能夠更加容易的讀懂(反向工程),

(2)生成的class文件會(huì)稍許大一些(不重要的),

(3)移除不被使用的本地變量的優(yōu)化功能將會(huì)失效。 換句話說,你在使用這個(gè)flag的時(shí)候不會(huì)遇到任何困難。如果不加上debug信息來編譯的話,Spring AOP將會(huì)嘗試推斷參數(shù)的綁定。 (例如,要是只有一個(gè)變量被綁定到切入點(diǎn)表達(dá)式(pointcut expression)、通知方法(advice method)將會(huì)接受這個(gè)參數(shù), 這是顯而易見的)。 如果變量的綁定不明確,將會(huì)拋出一個(gè) AmbiguousBindingException 異常。如果以上所有策略都失敗了,將會(huì)拋出一個(gè) IllegalArgumentException 異常。

6.3.3. 聲明通知和@AspectJ風(fēng)格一樣,基于schema的風(fēng)格也支持5種通知類型并且兩者具有同樣的語義。

6.3.3.1. 通知(Advice)Before通知在匹配方法執(zhí)行前進(jìn)入。在里面使用元素進(jìn)行聲明。 ...這里 dataAccessOperation 是一個(gè)頂級(jí)()切入點(diǎn)的id。 要定義內(nèi)置切入點(diǎn),可將 pointcut-ref 屬性替換為 pointcut 屬性: ...我們已經(jīng)在@AspectJ風(fēng)格章節(jié)中討論過了,使用命名切入點(diǎn)能夠明顯的提高代碼的可讀性。Method屬性標(biāo)識(shí)了提供了通知的主體的方法(doAccessCheck)。這個(gè)方法必須定義在包含通知的切面元素所引用的bean中。 在一個(gè)數(shù)據(jù)訪問操作執(zhí)行之前(執(zhí)行連接點(diǎn)和切入點(diǎn)表達(dá)式匹配),切面中的"doAccessCheck"會(huì)被調(diào)用。

6.3.3.2. 返回后通知(After returning advice)After returning通知在匹配的方法完全執(zhí)行后運(yùn)行。和Before通知一樣,可以在里面聲明。例如: ...和@AspectJ風(fēng)格一樣,通知主體可以接收返回值。使用returning屬性來指定接收返回值的參數(shù)名: ...doAccessCheck方法必須聲明一個(gè)名字叫 retVal 的參數(shù)。 參數(shù)的類型強(qiáng)制匹配,和先前我們?cè)?#64;AfterReturning中講到的一樣。例如,方法簽名可以這樣聲明:public void doAccessCheck(Object retVal) {...

6.3.3.3. 拋出異常后通知(After throwing advice)After throwing通知在匹配方法拋出異常退出時(shí)執(zhí)行。在 中使用after-throwing元素來聲明: ...和@AspectJ風(fēng)格一樣,可以從通知體中獲取拋出的異常。 使用throwing屬性來指定異常的名稱,用這個(gè)名稱來獲取異常: ...doRecoveryActions方法必須聲明一個(gè)名字為 dataAccessEx 的參數(shù)。 參數(shù)的類型強(qiáng)制匹配,和先前我們?cè)?#64;AfterThrowing中講到的一樣。例如:方法簽名可以如下這般聲明:public void doRecoveryActions(DataAccessException dataAccessEx) {...

6.3.3.4. 后通知(After (finally) advice)After (finally)通知在匹配方法退出后執(zhí)行。使用 after 元素來聲明: ...

6.3.3.5. 通知Around通知是最后一種通知類型。Around通知在匹配方法運(yùn)行期的“周圍”執(zhí)行。 它有機(jī)會(huì)在目標(biāo)方法的前面和后面執(zhí)行,并決定什么時(shí)候運(yùn)行,怎么運(yùn)行,甚至是否運(yùn)行。 Around通知經(jīng)常在需要在一個(gè)方法執(zhí)行前或后共享狀態(tài)信息,并且是線程安全的情況下使用(啟動(dòng)和停止一個(gè)計(jì)時(shí)器就是一個(gè)例子)。 注意選擇能滿足你需求的最簡(jiǎn)單的通知類型(i.e.如果簡(jiǎn)單的before通知就能做的事情絕對(duì)不要使用around通知)。Around通知使用 aop:around 元素來聲明。 通知方法的第一個(gè)參數(shù)的類型必須是 ProceedingJoinPoint 類型。 在通知的主體中,調(diào)用 ProceedingJoinPoint的proceed() 方法來執(zhí)行真正的方法。 proceed 方法也可能會(huì)被調(diào)用并且傳入一個(gè) Object[] 對(duì)象 - 該數(shù)組將作為方法執(zhí)行時(shí)候的參數(shù)。 參見 Section 6.2.4.5, “環(huán)繞通知(Around Advice)” 中提到的一些注意點(diǎn)。 ...doBasicProfiling 通知的實(shí)現(xiàn)和@AspectJ中的例子完全一樣(當(dāng)然要去掉注解):public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { // start stopwatch Object retVal = pjp.proceed(); // stop stopwatch return retVal;}6.3.3.6. 通知參數(shù)Schema-based聲明風(fēng)格和@AspectJ支持一樣,支持通知的全名形式 - 通過通知方法參數(shù)名字來匹配切入點(diǎn)參數(shù)。 參見 Section 6.2.4.6, “通知參數(shù)(Advice parameters)” 獲取詳細(xì)信息。如果你希望顯式指定通知方法的參數(shù)名(而不是依靠先前提及的偵測(cè)策略),可以通過 arg-names 屬性來實(shí)現(xiàn)。示例如下:The arg-names attribute accepts a comma-delimited list of parameter names.arg-names屬性接受由逗號(hào)分割的參數(shù)名列表。

總結(jié)

以上是生活随笔為你收集整理的使用Spring进行面向切面编程(AOP)---讲解+代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 绿帽人妻精品一区二区 | 国产精品女同一区二区 | 国产刺激对白 | 看日本黄色录像 | 体内精69xxxxxx | 天堂中文在线视频 | 日日夜夜噜 | 色5月婷婷 | 国产免费黄色小视频 | 日韩在线观看视频一区 | 在线免费观看成人 | 欧美一二三 | 黄色录像网址 | 农夫色综合 | 日韩三级中文字幕 | 国产自产21区 | 日韩一区在线观看视频 | 偷看洗澡一二三区美女 | 久久免费视频网站 | 福利综合网 | 中文字幕 人妻熟女 | 国产精品秘入口18禁麻豆免会员 | 亚洲成人久久精品 | 亚洲毛片av| 亚洲最大网站 | 亚洲AV无码成人精品区先锋 | 日韩精品短片 | 欧美一线天| 亚洲成人av一区 | 一区二区三区免费高清视频 | 亚洲国产精品欧美久久 | 欧美三级在线视频 | 国产深夜福利在线 | av毛片网 | 国产日产精品一区二区三区四区 | 三上悠亚人妻中文字幕在线 | 黄片毛片一级 | 久久一视频 | 日韩精品久久一区二区 | 99色影院 | 日韩中文字幕一区二区 | 日本视频免费观看 | 国产一级特黄aaa大片 | 99久久毛片 | 国产日韩视频一区 | 91成人黄色 | 日韩激情一区二区 | 99久久久无码国产精品性黑人 | 777777av| 日韩精品一区二区三区高清免费 | 成人动漫av | 国产欧美一区二区三区沐欲 | 91手机在线视频 | 打开每日更新在线观看 | 日韩中文在线视频 | 中国女人毛茸茸 | 成人a级片 | 亚洲天堂av影院 | 午夜精品久久久久久久无码 | 亚洲女优视频 | 欧美三级免费看 | 日本男女啪啪 | 国产精品午夜电影 | 深夜福利麻豆 | 一级特黄aa | 精品国产999久久久免费 | 一区二区三区毛片 | 九九精品久久 | 亚洲精品久久久久久 | 亚洲国产精品成人午夜在线观看 | 五月天婷婷社区 | 欧美二区视频 | 亚洲国产精品尤物yw在线观看 | 免费欧美 | 男人天堂2021 | 成都4电影免费高清 | 久久久香蕉 | 国模大胆一区二区三区 | 成年人免费看视频 | 国产精品一区视频 | 极品女神无套呻吟啪啪 | 色图色小说 | 青青草国产在线观看 | 欧美在线一级视频 | 69精品丰满人妻无码视频a片 | 日韩欧美高清 | 亚洲欧美精选 | 久久av资源网 | 91亚洲网| 国产不卡一 | 伊人手机在线视频 | 开心激情综合 | sao虎视频在线精品永久 | 天天躁日日躁狠狠躁av | 日本在线三级 | av中出| 秋霞在线观看视频 | 99人妻碰碰碰久久久久禁片 | 天天宗合 |