国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
[讀書筆記]Spring AOP Review - Robin‘s Java World ...
在 Spring 中所有的通知都是以 Java 類的形式編寫的。 Spring 是采用運(yùn)行期的方式來將切面織入到系統(tǒng)中的。代理 Bean 只有在第一次被應(yīng)用系統(tǒng)需要的時(shí)候才被創(chuàng)建。 Spring 有兩種方式創(chuàng)建代理: Proxy 類創(chuàng)建代理 ( 實(shí)現(xiàn)過接口的目標(biāo)類 ) 和運(yùn)用 CGLIB 庫創(chuàng)建代理 ( 沒有實(shí)現(xiàn)過任何接口的目標(biāo)類 ) 。需要注意兩點(diǎn): 1 、對(duì)接口創(chuàng)建代理優(yōu)于對(duì)類創(chuàng)建代理,因?yàn)檫@樣會(huì)產(chǎn)生更加松耦合的系統(tǒng), 2 、標(biāo)記為 final 的方法是不能被通知的,因?yàn)?Spring 在實(shí)現(xiàn)的時(shí)候是為目標(biāo)類產(chǎn)生子類。
Spring 只支持方法聯(lián)接點(diǎn)。
Spring 中通知的類型:
1 、 Around     org.aopalliance.intercept.MethodInterceptor        欄截對(duì)目標(biāo)對(duì)象方法的調(diào)用
2 、 Before       org.springframework.aop.MethodBeforAdvice     在目標(biāo)方法被調(diào)用之前調(diào)用
3 、 After        org.springframework.aop.AfterReturningAdvice  當(dāng)目標(biāo)方法被調(diào)用之后調(diào)用
4 、 Thorws     org.springframework.aop.ThrowsAdvice            當(dāng)目標(biāo)方法拋出異常時(shí)調(diào)用
前置通知 實(shí)現(xiàn) MethodBeforeAdvice 接口,該接口有以下方法:
void befor(Method method,Object []args,Object target) throws Throwable;
例:
public class WelcomeAdvice implements MethodBeforeAdvice{
public void before(Method method,Object []args,Object target){
System.out.println("Hello,"+((Customer)args[0]).getName());
}
}
配置文件如下:
<beans>
<bean id="aaaTargetObject" class="AAA"/>   // 目標(biāo)類 , 這是一個(gè)實(shí)現(xiàn)某個(gè)接口的類
<bean id="welcomeAdvice" class="WelcomeAdvice"/>  // 通知類
<bean id="aaa" class="org.springframework.aop.framework.proxyFactoryBean">
<property name="interceptorNames">
<list>
<value>welcomAdvice</value>
</list>
</property>
<property name="target">
<ref bean="aaaTargetObject"/>
</property>
</bean>
</beans>
后置通知 實(shí)現(xiàn) AfterReturningAdvice 接口,該接口有以下方法:
void afterReturning(Object returnValue,Method method,Object []args,Object target) throws Throwable;
例:
public class ThankYouAdvice implements AfterReturningAdvice{
public void afterReturning(Object returnValue,Method method,Object []args,Object target){
System.out.println("Thank you, come again.");
}
}
在前置通知和后置通知中都不能改變參數(shù)中傳進(jìn)來的值,改變執(zhí)行流程的惟一方法就是拋出異常。
環(huán)繞通知 實(shí)現(xiàn) MethodInterceptor 接口,該接口有以下方法:
Object invoke(MethodInvocation invocation) throws Throwable;
環(huán)繞通知能夠控制目標(biāo)方法是否真的被調(diào)用,通過調(diào)用 MethodInvocation.proceed() 方法來調(diào)用目標(biāo)方法。它還可以讓你控制返回的對(duì)象。
例:
public class ExampleAroundInterceptor implements MethodInterceptor{
public Object invoke(MethodInvocation invocation) throws Throwable{
// 調(diào)用之前可以做一些處理
Object returnObject=invocation.proceed();// 調(diào)用目標(biāo)方法
// 調(diào)用之后還可以做一些處理
return returnObject;
}
}
異常通知 實(shí)現(xiàn) ThrowsAdvice 接口,此接口是一個(gè)標(biāo)示接口,沒有定義必須實(shí)現(xiàn)的方法,但是下面兩個(gè)方法中必須實(shí)現(xiàn)一個(gè):
void afterThrowing(Throwable throwable);
void afterThrowing(Method method,Object []args,Object target,Throwable throwable);
ThrowsAdvice 要處理的異常取決于你的方法定義的異常類型,在一個(gè)實(shí)現(xiàn)類中,也可以實(shí)現(xiàn)多個(gè) afterThrowing 方法,根據(jù)拋出的異常類型調(diào)用適當(dāng)?shù)姆椒ā?div style="height:15px;">
引入通知 給目標(biāo)對(duì)象添加新的方法 ( 以及屬性 ) 。
定義切入點(diǎn)
切入點(diǎn) 就是應(yīng)用通知的地方,切入點(diǎn)決定了一個(gè)特定的類的特定方法是否滿足一條特定的規(guī)則,如果一個(gè)方法符合的話,通知就應(yīng)用到該方法上。 Spring 的切入點(diǎn)可以讓我們以一種靈活的方式定義在什么地方將通知織入到我們的類中。
切入點(diǎn)的核心接口是 Pointcut 接口,同時(shí)它也需要兩個(gè)接口支持,如下:
public interface Pointcut{
ClassFilter getClassFilter(); // 決定一個(gè)類是否符合要求
MethodMatcher getMethodMatcher(); // 決定一個(gè)方法是否符合要求
}
public interface ClassFilter{
boolean matches(Class clazz);
}
此接口總是包含一個(gè)簡單的 ClassFilter 接口的實(shí)現(xiàn) --ClassFilter.TRUE ,它是規(guī)范的適合任何類的 ClassFilter 實(shí)例,它適合于只根據(jù)方法決定什么時(shí)候符合要求的切入點(diǎn)。
public interface MethodMatcher{
boolean matches(Method m,class targetClass);// 靜態(tài)的決定一個(gè)方法是否被通知織入
public boolean isRuntime();// 決定是靜態(tài)的還是動(dòng)態(tài)的織入
public boolean mathes(Method m,Class targetClass,Object []args);// 動(dòng)態(tài)的決定一個(gè)方法是否被通知織入,系統(tǒng)開銷會(huì)增加,不推薦使用
}
大多數(shù)的切面是由定義切面行為的通知和定義切面在什么地方執(zhí)行的切入點(diǎn)給合而成的, Spring 為此提供了 Advisor ,它把通知和切入點(diǎn)組合到一個(gè)對(duì)象中。接口 PointcutAdvisor 提供了這些功能,接口如下:
public interface PointcutAdvisor{
Pointcut getPointcut();
Advice getAdvice();
}
大多數(shù) Spring 自帶的切入點(diǎn)都有一個(gè)對(duì)應(yīng)的 PointcutAdvisor 。這樣方便你在一個(gè)地方定義通知和切入點(diǎn)。
使用 Spring 的靜態(tài)切入點(diǎn) :
Spring 為創(chuàng)建靜態(tài)切入點(diǎn)提供了方便的父類: StaticMethodMatcherPointcut 。如果想自定義靜態(tài)切入點(diǎn)的話,繼承這個(gè)類,并實(shí)現(xiàn) isMatch 方法就 OK 了。
Spring 提供了一個(gè)靜態(tài)切入點(diǎn)的實(shí)現(xiàn)類: NameMatchMethodPointcut 。它有如下兩個(gè)方法:
Public void setMappedName(String);
Public void setMappedNames(String []);
這個(gè)類通過名字映射,上面兩個(gè)方法的參數(shù)中均可以使用通配符 * 。
規(guī)則表達(dá)式切入點(diǎn), Spring 提供了 RegexpMethodPointcut 讓你利用正則表達(dá)式的力量來定義切入點(diǎn)。
符號(hào)
描述
示例
.
匹配任何單個(gè)字符
setFoo. 匹配 setFooB, 但不匹配 setFoo 或 setFooBar
+
匹配前一個(gè)字符一次或多次
setFoo.+ 匹配 setFooBar 和 setFooB, 但不匹配 setFoo
*
匹配前一個(gè)字符 0 次或多次
setFoo.* 匹配 setFoo,setFooB 和 setFooBar
\
匹配任何正則表達(dá)式符號(hào)
\.setFoo. 匹配 bar.setFoo, 但不匹配 setFoo
如果你想匹配所有 setXxx 方法,我們需要使用 .*set*. 模版 ( 第一個(gè)通配符匹配任何類名。筆者認(rèn)為此處《 Spring in action 》一書中有誤,我認(rèn)為此處應(yīng)為 .*set.*) 。如果使用 RegexpMethodPointcut ,你需要在你的應(yīng)用系統(tǒng)中引入 ORO 類庫。
<bean id=”queryPointcutAdvisor”
Class=”org.springframework.aop.support.RegExPointcutAdvisor”>
<property name=”pattern”>
<value>.*get.+By.+</value>
</property>
<property name=”advice”>
<ref bean=”queryInterceptor”/>
</property>
</bean>
使用動(dòng)態(tài)切入點(diǎn)
Spring 提供了一種內(nèi)置的動(dòng)態(tài)切入點(diǎn): ControlFlowPointcut 。這個(gè)切入點(diǎn)根據(jù)線程調(diào)用堆棧的信息來匹配方法。也就是說,它可以配置成只有當(dāng)指定方法或類能在當(dāng)前線程執(zhí)行堆棧中找到時(shí),返回 true 。
<bean id=”servletPointcut” class=”org.springframework.aop.support.ControlFlowPointcut”>
<construct-arg>
<value>javax.servlet.http.HttpServlet</value>
</construct-arg>
</bean>
<bean id=”servletAdvisor” class=”org.springframework.aop.support.DefaultPointcutAdvisor”>
<property name=”advice”>
<ref bean=”servletInterceptor”/>
</property>
<property name=”pointcut”>
<ref bean=”servletPointcut”/>
</property>
</bean>
注: ControlFlowPointcut 明顯比其他的動(dòng)態(tài)切入點(diǎn)慢。
切入點(diǎn)實(shí)施
Spring 支持在切入點(diǎn)上進(jìn)行操作 — 合并與產(chǎn)叉 — 來創(chuàng)建新的切入點(diǎn)。只有當(dāng)切入點(diǎn)都匹配時(shí)交叉集合才匹配,任何一個(gè)切入點(diǎn)匹配都會(huì)使合并集合匹配。 Spring 為創(chuàng)建這兩種切入點(diǎn)提供了兩個(gè)類:第一個(gè)類是 ComposablePointcut 。通過將已有的 ComposablePointcut 、切入點(diǎn)、 MethodMatcher 以及 ClassFilter 對(duì)象進(jìn)行合并或交叉,組裝成一個(gè)新的 ComposablePointcut 對(duì)象。這可以通過調(diào)用 ComposablePointcut 實(shí)例的 intersection () 或 union () 方法實(shí)現(xiàn)。
ComposablePointcut cp=new ComposablePoint()
cp=p.intersection(myPointcut).union(myMethodmatcher);
為了對(duì)兩個(gè) Pointcut 對(duì)象進(jìn)行合并,必須使用 Pointcuts 類。這是一個(gè)工具類,它擁有很多操作 Pointcut 對(duì)象的靜態(tài)方法。如:
Pointcut union=Pointcuts.union(pointcut1,pointcut2);
創(chuàng)建引入
引入與其他類型的 Spring 通知有所不同。其它類型通知是在方法調(diào)用的周圍織入到不同的連接點(diǎn),而引入則是影響整個(gè)類,他們通過給需要消息的類型添加方法和屬性來實(shí)現(xiàn)。也就是說,你可以用一個(gè)已存在的類讓它實(shí)現(xiàn)另外的接口,維持另外的狀態(tài) ( 這也叫混合 ) 。換句話說,引入讓你能夠動(dòng)態(tài)地建立復(fù)合對(duì)象,提供了多態(tài)繼承的好處。
實(shí)現(xiàn) IntroductionInterceptor
Spring 通過一個(gè)特殊的方法攔截器接口 IntroductionMethodInterceptor 來實(shí)現(xiàn)引入。這個(gè)接口有一個(gè)方法:
Boolean implementsInterface(Class intf);
如果 IntroductionMethodInterceptor 是為了實(shí)現(xiàn)指定接口,那么方法 implementsInterface 應(yīng)該返回 true 。就是說,對(duì)用這個(gè)接口聲明的方法的任何調(diào)用將被委托給 IntroductionMethodInterceptor 的 invoke() 方法。 Invoke() 方法負(fù)責(zé)實(shí)現(xiàn)這個(gè)方法,不能調(diào)用 MethodInvocation.proceed() 。它引入了新的接口,調(diào)用目標(biāo)對(duì)象是沒有用的。
使用 ProxyBeanFactory
BeanFactory 對(duì)象是一個(gè)負(fù)責(zé)創(chuàng)建其他 JavaBean 的 JavaBean 。屬性列表如下:
屬性
使  用
target
代理的目標(biāo)對(duì)象
proxyInterfaces
代理應(yīng)該實(shí)現(xiàn)的接口列表
interceptorNames
需要應(yīng)用到目標(biāo)對(duì)象上的通知 Bean 的名字??梢允菙r截器, Advisor 或其他通知類型的名字。這個(gè)屬性必須按照在 BeanFactory 中使用的順序設(shè)置。
singleton
是否返回的是同一個(gè)代理實(shí)例。如果使用的是狀態(tài)通知,應(yīng)該設(shè)置為 false
aopProxyFactory
使用的 ProxyFactoryBean 實(shí)現(xiàn)
exposeProxy
目標(biāo)對(duì)象是否需要得到當(dāng)前的代理。通過調(diào)用 AopContext.getCurrentProxy 實(shí)現(xiàn)。記住這樣做會(huì)在你的代碼中引入 Spring 專有的 AOP 代碼,所以,盡量避免使用。
frozen
一旦工廠被創(chuàng)建,是否可以修改代理的通知。
optimize
是否對(duì)創(chuàng)建的代理進(jìn)行優(yōu)化 ( 僅適用于 CGLIB) 。
ProxyTargetClass
是否代理目標(biāo)類,而不是實(shí)現(xiàn)接口。 ( 需要 CGLIB 支持 )
大多數(shù)情況下我們只用到前三個(gè)屬性。
如果想避免將目標(biāo)對(duì)象暴露給系統(tǒng)中其他 Bean 的話,可以將它聲明為一個(gè)內(nèi)部 Bean 。
proxyInterfaces 屬性指定了從工廠中創(chuàng)建的 Bean 需要實(shí)現(xiàn)的接口。如:
<property name=”proxyInterfaces”>
<value>com.springinaction.service.CourseService</value>
</property>
這樣就讓 ProxyBeanFactory 知道它創(chuàng)建的所有 Bean 都要實(shí)現(xiàn) CourseService 接口??梢韵襁@樣只提供一個(gè)接口,也可以用 <list> 提供多個(gè)接口。
interceptorNames 屬性定義了一個(gè)應(yīng)用到目標(biāo)對(duì)象上的 Advisor 或通知 Bean 的列表。目標(biāo) Bean 也可以放在此屬性的 <list> 列表的最后,但是最好還是用 Target 屬性設(shè)置目標(biāo) Bean 。
自動(dòng)代理
Spring 有一個(gè)自動(dòng)代理機(jī)制,它可以讓容器為我們產(chǎn)生代理。 Spring 有兩個(gè)類提供這種服務(wù): BeanNameAutoProxyCreator 和 DefaultAdvisorAutoProxyCreator 。
BeanNameAutoProxyCreator 為匹配一系列名字的 Bean 自動(dòng)創(chuàng)建代理。它允許在名字的兩端進(jìn)行通配符匹配。通常用于為符合相同命名規(guī)則的 Bean 應(yīng)用一個(gè)或一組切面 。 ( 主要是解決 target 屬性配置時(shí)目標(biāo)類過多的問題。 ) 如:
<bean id=”preformanceThresholdProxyCreator
Class=”org.springframework.aop.framework.autoproxy.BeanNameAutoProxyProlyCreator”>
<property name=”beanNames”>
<list>
<value>*Service</value>
</list>
</property>
<propery name=”interceptorNames”>
<value>performaceThresholdInterceptor</value>
</property>
</bean>
如果 Bean 是一個(gè) Advisor 或攔截器,它將應(yīng)用到代理對(duì)象的所有方法上。如果是通知的話, Advisor 切入點(diǎn)會(huì)根據(jù)不同 Bean 將通知應(yīng)用到不同的地方。
自動(dòng)代理框架對(duì)于代理需要暴露哪些接口作了一些假設(shè)。目標(biāo)對(duì)象實(shí)現(xiàn)的任何接口代理對(duì)象都要暴露出來。如果目標(biāo)類沒有實(shí)現(xiàn)任何接口,那么應(yīng)用于前面討論過的 ProxyFactoryBean 一樣的規(guī)則 — 動(dòng)態(tài)生成一個(gè)子類。
DefaultAdvisorAutoProxyCreator
這個(gè)類的奇妙之處在于它實(shí)現(xiàn)了 BeanPostProcessor 接口。當(dāng) ApplicationContext 讀入所有 Bean 的配置信息后, DefaultAdvisorAutoProxyCreator 將掃描上下文,尋找所有的 Advisor 。它將這些 Advisor 應(yīng)用到所有符合 Advisor 切入點(diǎn)的 Bean 中。這個(gè)代理創(chuàng)建器只能與 Advisor 配合使用 。 ( 我們知道,一個(gè) Advisor 是一個(gè)切入點(diǎn)和一個(gè)通知的結(jié)合體。 DefaultAdvisorAutoProxyCreator 需要 Advisor 來知道哪些 Bean 需要通知。 )
<bean id=”advisor” class=”org.springframework.aop.support.RegexpMethodPointcutAdvisor”>
<property name=”advice”>
<bean class=”performaceThresholdInterceptor”/>
</property>
<property name=”pattern”>
<value>.+Service\..+</value>
</property>
</bean>
<bean id=”autoProxyCreator”
class=”org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator”/>
在讀入所有 Bean 的定義信息后, BeanFactory 中的所有 Advisor 將被釋放出來。它們會(huì)將它們的通知配置到任何匹配它們的切入點(diǎn)的 Bean 上 ( 這就是它真正的威力 ) 。
不用顯示地將 Advisor 與其他東西結(jié)合,現(xiàn)在只要簡單地定義它們,然后讓它們自動(dòng)地應(yīng)用到它們匹配的地方。這樣松耦合 Bean 以及它們的通知就實(shí)現(xiàn)了。
Spring 也支持通過元數(shù)據(jù) (Metadata) 驅(qū)動(dòng)自動(dòng)代理。這種類型自動(dòng)代理,代理配置是通過源代碼屬性而不是外部配置文件獲得的。最常見的元數(shù)據(jù)自動(dòng)配置是聲明式事務(wù)支持。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Spring AOP原理及攔截器
【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學(xué)spring3
spring aop術(shù)語解釋
Spring.NET 中的 AOP
用Spring AOP實(shí)現(xiàn)開發(fā)中松散耦合-軟件頻道-Spring-天極網(wǎng)
Spring AOP學(xué)習(xí)4 - 使用基于Aspectj風(fēng)格配置AOP-3 配置詳解
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服