Spring AOP四種創(chuàng)建通知(攔截器)類型實(shí)例
系統(tǒng)
2019-08-12 09:29:32
1953 0
1、Spring只支持方法攔截,也就是說,只能在方法的前后進(jìn)行攔截,而不能在屬性前后進(jìn)行攔截。
2、Spring支持四種攔截類型:目標(biāo)方法調(diào)用前(before),目標(biāo)方法調(diào)用后(after),目標(biāo)方法調(diào)用前后(around),以及目標(biāo)方法拋出異常(throw)。
3、前置攔截的類必須實(shí)現(xiàn)MethodBeforeAdvice接口,實(shí)現(xiàn)其中的before方法。
4、后置攔截的類必須實(shí)現(xiàn)AfterReturningAdvice接口,實(shí)現(xiàn)其中的afterReturning方法。
5、前后攔截的類必須實(shí)現(xiàn)MethodInterceptor接口,實(shí)現(xiàn)其中的invoke方法。前后攔截是唯一可以控制目標(biāo)方法是否被真正調(diào)用的攔截類型,也可以控制返回對象。而前置攔截或后置攔截不能控制,它們不能印象目標(biāo)方法的調(diào)用和返回。
但是以上的攔截的問題在于,不能對于特定方法進(jìn)行攔截,而只能對某個類的全部方法作攔截。所以下面引入了兩個新概念:“切入點(diǎn)”和“引入通知”。
6、”切入點(diǎn)“的定義相當(dāng)于更加細(xì)化地規(guī)定了哪些方法被哪些攔截器所攔截,而并非所有的方法都被所有的攔截器所攔截。在ProxyFactoryBean的屬性中,interceptorNames屬性的對象也由攔截(Advice)變成了引入通知(Advisor),正是在Advisor中詳細(xì)定義了切入點(diǎn)(PointCut)和攔截(Advice)的對應(yīng)關(guān)系,比如常見的基于名字的切入點(diǎn)匹配(NameMatchMethodPointcutAdvisor類)和基于正則表達(dá)式的切入點(diǎn)匹配(RegExpPointcutAdvisor類)。這些切入點(diǎn)都屬于”靜態(tài)切入點(diǎn)“,因為他們只在代理創(chuàng)建的時候被創(chuàng)建一次,而不是每次運(yùn)行都創(chuàng)建。
?
下面我們進(jìn)行實(shí)例的開發(fā)
?
首先創(chuàng)建業(yè)務(wù)接口:
?
package
?AdvisorTest;
public
?
interface
?Shopping?
...
{
??
public
?String?buySomething(String?type);
??
public
?String?buyAnything(String?type);
??
public
?
void
?testException();
}
?下面是業(yè)務(wù)實(shí)現(xiàn)類,我們的通知就是以這些實(shí)現(xiàn)類作為切面,在業(yè)務(wù)方法前后加入我們的通知代碼
?
package
?AdvisorTest;
public
?
class
?ShoppingImpl?
implements
?Shopping?
...
{
????
private
?Customer?customer;
????
public
?Customer?getCustomer()?
...
{
????????
return
?customer;
????}
????
public
?
void
?setCustomer(Customer?customer)?
...
{
????????
this
.customer?
=
?customer;
????}
????
public
?String?buySomething(String?type)?
...
{
????????System.out.println(
this
.getCustomer().getName()
+
"
?bye?
"
+
type
+
"
?success
"
);
????????
return
?
null
;
????}
????
????
public
?String?buyAnything(String?type)?
...
{
???????System.out.println(
this
.getCustomer().getName()
+
"
?bye?
"
+
type
+
"
?success
"
);
???????
return
?
null
;
?????}
????
public
?
void
?testException()
...
{
????????
throw
?
new
?ClassCastException();
????}
}
?
(1)前置通知
??????? 配置了前置通知的bean,在執(zhí)行業(yè)務(wù)方法前,均會執(zhí)行前置攔截器的before方法
package
?AdvisorTest;
import
?java.lang.reflect.Method;
import
?org.springframework.aop.MethodBeforeAdvice;
//
前置通知
public
?
class
?WelcomeAdvice?
implements
?MethodBeforeAdvice?
...
{
????
public
?
void
?before(Method?method,?Object[]?args,?Object?obj)
????????????
throws
?Throwable?
...
{
????????String?type
=
(String)args[
0
];
????????System.out.println(
"
Hello?welcome?to?bye?
"
+
type);
????}
}
?
(2)后置通知
配置了前置通知的bean,在執(zhí)行業(yè)務(wù)方法前,均會執(zhí)行前置攔截器的afterReturnning方法
?
package
?AdvisorTest;
import
?java.lang.reflect.Method;
import
?org.springframework.aop.AfterReturningAdvice;
import
?org.springframework.aop.MethodBeforeAdvice;
//
后置通知
public
?
class
?ThankYouAdvice?
implements
?AfterReturningAdvice?
...
{
????
public
?
void
?afterReturning(Object?obj,?Method?method,?Object[]?arg1,
????????????Object?arg2)?
throws
?Throwable?
...
{
????????
?????????String?type
=
(String)arg1[
0
];
?????????System.out.println(
"
Hello?Thankyou?to?bye?
"
+
type);
????}
????
}
?
(3)環(huán)繞通知
配置了前置通知的bean,在執(zhí)行業(yè)務(wù)方法前后,均會執(zhí)行前置攔截器的invoke方法
需要注意的是必須調(diào)用目標(biāo)方法,如不調(diào)用,目標(biāo)方法將不被執(zhí)行
package
?AdvisorTest;
import
?org.aopalliance.intercept.MethodInterceptor;
import
?org.aopalliance.intercept.MethodInvocation;
public
?
class
?MethodAdvisor?
implements
?MethodInterceptor?
...
{
????
public
?Object?invoke(MethodInvocation?invocation)?
throws
?Throwable?
...
{
????????String?str
=
(String)invocation.getArguments()[
0
];
????????System.out.println(
"
this?is?before
"
+
str
+
"
?in?MethodInterceptor
"
);
????????Object?obj
=
invocation.proceed();?
//
調(diào)用目標(biāo)方法,如不調(diào)用,目標(biāo)方法將不被執(zhí)行
????????System.out.println(
"
this?is?after
"
+
str
+
"
?in?MethodInterceptor
"
);
????????
return
?
null
;
????}
}
?
(4)異常通知
ThrowsAdvice是一個標(biāo)示接口,我們可以在類中定義一個或多個,來捕獲定義異常通知的
bean拋出的異常,并在拋出異常前執(zhí)行相應(yīng)的方法
public void afterThrowing(Throwable throwa){}
或者
public void afterThrowing(Method method,Object[] args,Object target,Throwable throwable){
package
?AdvisorTest;
import
?org.springframework.aop.ThrowsAdvice;
public
??
class
?ExceptionAdvisor?
implements
?ThrowsAdvice?
...
{
??
public
?
void
?afterThrowing(ClassCastException?e)
...
{
??????System.out.println(
"
this?is?from?exceptionAdvisor
"
);
??}
}
?
配置文件
?
<?
xml?version="1.0"?encoding="UTF-8"
?>
<!
DOCTYPE?beans?PUBLIC?"-//SPRING//DTD?BEAN//EN"?"http://www.springframework.org/dtd/spring-beans.dtd"?
>
<
beans
>
?
<
bean?
id
="customer"
?class
="AdvisorTest.Customer"
>
???
<
constructor-arg?
index
="0"
>
?????
<
value
>
gaoxiang
</
value
>
???
</
constructor-arg
>
????
<
constructor-arg?
index
="1"
>
?????
<
value
>
26
</
value
>
???
</
constructor-arg
>
?
</
bean
>
?
?
<
bean?
id
="shoppingImpl"
?class
="AdvisorTest.ShoppingImpl"
>
???
<
property?
name
="customer"
>
?????
<
ref?
local
="customer"
/>
???
</
property
>
?
</
bean
>
<!--
?前置通知?
-->
<
bean?
id
="welcomeAdvice"
?class
="AdvisorTest.WelcomeAdvice"
/>
<
bean?
id
="welcomeAdviceShop"
?class
="org.springframework.aop.framework.ProxyFactoryBean"
>
??
<
property?
name
="proxyInterfaces"
>
????
<
value
>
AdvisorTest.Shopping
</
value
>
??
</
property
>
??
<
property?
name
="target"
>
????
<
ref?
local
="shoppingImpl"
/>
??
</
property
>
??
<
property?
name
="interceptorNames"
>
????
<
list
>
??????
<
value
>
welcomeAdvice
</
value
>
????
</
list
>
??
</
property
>
??
</
bean
>
<!--
?后置通知?
-->
<
bean?
id
="thankyouAdvice"
?class
="AdvisorTest.ThankYouAdvice"
/>
<
bean?
id
="thankyouAdviceShop"
?class
="org.springframework.aop.framework.ProxyFactoryBean"
>
??
<
property?
name
="proxyInterfaces"
>
????
<
value
>
AdvisorTest.Shopping
</
value
>
??
</
property
>
??
<
property?
name
="target"
>
????
<
ref?
local
="shoppingImpl"
/>
??
</
property
>
??
<
property?
name
="interceptorNames"
>
????
<
list
>
??????
<
value
>
thankyouAdvice
</
value
>
????
</
list
>
??
</
property
>
??
</
bean
>
<!--
?環(huán)繞通知?
-->
<
bean?
id
="methodAdvice"
?class
="AdvisorTest.MethodAdvisor"
/>
<
bean?
id
="methodAdviceShop"
?class
="org.springframework.aop.framework.ProxyFactoryBean"
>
??
<
property?
name
="proxyInterfaces"
>
????
<
value
>
AdvisorTest.Shopping
</
value
>
??
</
property
>
??
<
property?
name
="target"
>
????
<
ref?
local
="shoppingImpl"
/>
??
</
property
>
??
<
property?
name
="interceptorNames"
>
????
<
list
>
??&nb
Spring AOP四種創(chuàng)建通知(攔截器)類型實(shí)例
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】 元
喜歡作者