?
本文檔使用 PHP中文網(wǎng)手冊(cè) 發(fā)布
在創(chuàng)建了AOP代理之后,你能夠使用org.springframework.aop.framework.Advised
接口對(duì)它們進(jìn)行管理。
任何AOP代理都能夠被轉(zhuǎn)型為這個(gè)接口,不論它實(shí)現(xiàn)了哪些其它接口。這個(gè)接口包括下面的方法:
Advisor[] getAdvisors(); void addAdvice(Advice advice) throws AopConfigException; void addAdvice(int pos, Advice advice) throws AopConfigException; void addAdvisor(Advisor advisor) throws AopConfigException; void addAdvisor(int pos, Advisor advisor) throws AopConfigException; int indexOf(Advisor advisor); boolean removeAdvisor(Advisor advisor) throws AopConfigException; void removeAdvisor(int index) throws AopConfigException; boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException; boolean isFrozen();
getAdvisors()
方法將為每個(gè)已經(jīng)被加入工廠的通知器,攔截器或者其它通知類型返回一個(gè)通知器。如果你曾經(jīng)添加一個(gè)通知器,那么所返回的通知器將是你加入的對(duì)象。
如果你曾經(jīng)加入一個(gè)攔截器或者其它通知類型,Spring將把它們包裝在一個(gè)通知器里,后者使用一個(gè)永遠(yuǎn)返回true的切入點(diǎn)。因此如果你曾經(jīng)加入一個(gè)MethodInterceptor
,
返回的通知器將是一個(gè)DefaultPointcutAdvisor
,它可以返回你加入的MethodInterceptor
和一個(gè)匹配所有類和方法的切入點(diǎn)。
addAdvisor()
方法可以用來添加任何通知器。通常保存切入點(diǎn)和通知的通知器是DefaultPointcutAdvisor
,它可以用于任何通知或切入點(diǎn)(但不包括引入類型)。
缺省情況下,你可以加入或移除通知器或者攔截器甚至當(dāng)代理已經(jīng)被創(chuàng)建之后。唯一的限制是無法加入或者移除一個(gè)引入通知器,因?yàn)楣S中獲得的已有代理不能顯示接口的改變(你可以通過從工廠里獲取一個(gè)新的代理來避免這個(gè)問題)。
下面是一個(gè)簡(jiǎn)單的例子,它把一個(gè)AOP代理轉(zhuǎn)型為Advised
接口,檢查并操作它的通知:
Advised advised = (Advised) myObject; Advisor[] advisors = advised.getAdvisors(); int oldAdvisorCount = advisors.length; System.out.println(oldAdvisorCount + " advisors"); // Add an advice like an interceptor without a pointcut // Will match all proxied methods // Can use for interceptors, before, after returning or throws advice advised.addAdvice(new DebugInterceptor()); // Add selective advice using a pointcut advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice)); assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length);
在一個(gè)實(shí)際運(yùn)行的系統(tǒng)里,修改一個(gè)業(yè)務(wù)對(duì)象上的通知是否明智是個(gè)問題,雖然無疑在某些情況下這樣做是合理的。然而這在開發(fā)中是很有用的: 例如,在測(cè)試的時(shí)候。對(duì)于希望測(cè)試的方法調(diào)用,有時(shí)我發(fā)現(xiàn)把測(cè)試代碼加入到一個(gè)攔截器或者其它通知里是非常有用的。 (例如,通知可以與目標(biāo)方法存在于同一個(gè)事務(wù)里,在把事務(wù)標(biāo)記為回滾之前可以用SQL來檢查數(shù)據(jù)庫(kù)是否被正確的更新了。)
依賴于你怎樣創(chuàng)建代理,你通??梢栽O(shè)置一個(gè)
frozen
標(biāo)志,在這種情況下
Advised
的isFrozen()
方法將返回true,任何增加或者移除通知的修改都會(huì)導(dǎo)致一個(gè)AopConfigException
異常。
在某些情況下這種凍結(jié)被通知對(duì)象狀態(tài)的能力是很有用的:例如,防止調(diào)用代碼來移除一個(gè)進(jìn)行安全檢查的攔截器。在Spring 1.1中它也被用來允許激進(jìn)優(yōu)化,如果已經(jīng)知道不需要運(yùn)行時(shí)對(duì)通知進(jìn)行修改的話。