Spring AOP四種創建通知(攔截器)類型實例
系統
2019-08-12 09:29:32
2037 0
1、Spring只支持方法攔截,也就是說,只能在方法的前后進行攔截,而不能在屬性前后進行攔截。
2、Spring支持四種攔截類型:目標方法調用前(before),目標方法調用后(after),目標方法調用前后(around),以及目標方法拋出異常(throw)。
3、前置攔截的類必須實現MethodBeforeAdvice接口,實現其中的before方法。
4、后置攔截的類必須實現AfterReturningAdvice接口,實現其中的afterReturning方法。
5、前后攔截的類必須實現MethodInterceptor接口,實現其中的invoke方法。前后攔截是唯一可以控制目標方法是否被真正調用的攔截類型,也可以控制返回對象。而前置攔截或后置攔截不能控制,它們不能印象目標方法的調用和返回。
但是以上的攔截的問題在于,不能對于特定方法進行攔截,而只能對某個類的全部方法作攔截。所以下面引入了兩個新概念:“切入點”和“引入通知”。
6、”切入點“的定義相當于更加細化地規定了哪些方法被哪些攔截器所攔截,而并非所有的方法都被所有的攔截器所攔截。在ProxyFactoryBean的屬性中,interceptorNames屬性的對象也由攔截(Advice)變成了引入通知(Advisor),正是在Advisor中詳細定義了切入點(PointCut)和攔截(Advice)的對應關系,比如常見的基于名字的切入點匹配(NameMatchMethodPointcutAdvisor類)和基于正則表達式的切入點匹配(RegExpPointcutAdvisor類)。這些切入點都屬于”靜態切入點“,因為他們只在代理創建的時候被創建一次,而不是每次運行都創建。
?
下面我們進行實例的開發
?
首先創建業務接口:
?
package
?AdvisorTest;
public
?
interface
?Shopping?
...
{
??
public
?String?buySomething(String?type);
??
public
?String?buyAnything(String?type);
??
public
?
void
?testException();
}
?下面是業務實現類,我們的通知就是以這些實現類作為切面,在業務方法前后加入我們的通知代碼
?
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,在執行業務方法前,均會執行前置攔截器的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,在執行業務方法前,均會執行前置攔截器的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)環繞通知
配置了前置通知的bean,在執行業務方法前后,均會執行前置攔截器的invoke方法
需要注意的是必須調用目標方法,如不調用,目標方法將不被執行
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();?
//
調用目標方法,如不調用,目標方法將不被執行
????????System.out.println(
"
this?is?after
"
+
str
+
"
?in?MethodInterceptor
"
);
????????
return
?
null
;
????}
}
?
(4)異常通知
ThrowsAdvice是一個標示接口,我們可以在類中定義一個或多個,來捕獲定義異常通知的
bean拋出的異常,并在拋出異常前執行相應的方法
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
>
<!--
?環繞通知?
-->
<
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四種創建通知(攔截器)類型實例
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】 元
喜歡作者