一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 談?wù)凷pring AOP中@Aspect的高級用法示例

談?wù)凷pring AOP中@Aspect的高級用法示例

2021-05-26 13:35deniro Java教程

在Spring AOP中目前只有執(zhí)行方法這一個連接點,下面這篇文章主要給大家介紹了關(guān)于Spring AOP中@Aspect的高級用法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

本文主要跟大家分享介紹了關(guān)于spring aop中@aspect的高級用法,下面話不多說了,來隨著小編一起看看詳細(xì)的介紹吧。

1 切點復(fù)合運算

支持在切點定義中加入以下運算符進行復(fù)合運算:

 

運算符 說明
&& 與運算。
! 非運算。
|| 或運算。

 

2 切點命名

一般情況下,切點是直接聲明在需要增強方法處,這種切點的聲明方式稱為匿名切點,匿名切點只能在聲明處被使用 。 如果希望在其它地方可以重用這個切點,我們可以通過 @pointcut 注解及切面類方法來命名它。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class namepointcut {
 
 /**
 * 切點被命名為 method1,且該切點只能在本類中使用
 */
 @pointcut("within(net.deniro.spring4.aspectj.*)")
 private void method1() {
 }
 
 /**
 * 切點被命名為 method2,且該切點可以在本類或子孫類中使用
 */
 @pointcut("within(net.deniro.spring4.aspectj.*)")
 protected void method2() {
 }
 
 /**
 * 切點被命名為 method3,且該切點可以在任何類中使用
 * 這里還使用了復(fù)合運算
 */
 @pointcut("method1() && method2()")
 public void method3() {
 }
}

命名切點的結(jié)構(gòu)如下:

談?wù)凷pring AOP中@Aspect的高級用法示例

切點可訪問性修飾符與類可訪問性修飾符的功能是相同的,它可以決定定義的切點可以在哪些類中可使用。

因為命名切點僅利用方法名及訪問修飾符的信息,所以我們一般定義方法的返回類型為 void ,并且方法體為空 。

定義好切點后,就可以在切面類中引用啦:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@aspect
public class namepointcutaspect {
 
 @after("namepointcut.method2()")
 public void aspectmethod1() {
 }
 
 /**
 * 這里使用了復(fù)合運算
 */
 @after("namepointcut.method2() && namepointcut.method3()")
 public void aspectmethod2() {
 }
}

3 織入順序

一個連接點可以同時匹配多個切點,而切點所對應(yīng)的增強在連接點上織入順序的規(guī)則是這樣的:

1.如果在同一個切面類中聲明的增強,則按照增強在切面類中定義的順序進行織入;

2.如果增強位于不同的切面類中,并且這些切面類都實現(xiàn)了org.springframework.core.ordered 接口,則由 ordered 方法的順序號決定(順序號小的先織入);

3.如果增強位于不同的切面類中,但這些切面類沒有實現(xiàn)org.springframework.core.ordered 接口,織入的順序是不確定的 。

假設(shè)有兩個切面類 a 與 b,它們都實現(xiàn)了 ordered 接口,a 的順序號為 1,b 的順序號為 2,切面類 a 與 b 都定義了 3 個增強,那么同時匹配這 6 個增強的織入順序如下圖所示:

談?wù)凷pring AOP中@Aspect的高級用法示例

4 獲取連接點信息

4.1 joinpoint

org.aspectj.lang.joinpoint 接口表示目標(biāo)類連接點對象,它定義這些主要方法。

 

方法 說明
object[] getargs() 獲取連接點方法運行時的入?yún)⒘斜怼?/td>
signature getsignature() 獲取連接點的方法簽名對象。
object gettarget() 獲取連接點所在的目標(biāo)對象。
object getthis() 獲取代理對象。

 

4.2 proceedingjoinpoint

org.aspectj.lang.proceedingjoinpoint 繼承了 joinpoint 接口,它新增了兩個方法(它們用于執(zhí)行連接點方法)。

方法 說明
object proceed() throws throwable 通過反射執(zhí)行目標(biāo)對象連接點處的方法。
object proceed(object[] var1) throws throwable 使用新的入?yún)ⅲㄌ鎿Q掉原來的入?yún)ⅲㄟ^反射執(zhí)行目標(biāo)對象連接點處的方法。

4.3 示例

cook 接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface cook {
 
 /**
 * 制作食品
 */
 void make();
 
 /**
 * 制作
 *
 * @param name 食品名稱
 */
 void make(string name);
}

cooka 類:

?
1
2
3
4
5
6
7
8
9
public class cooka implements cook {
 public void make() {
 system.out.println("制作食品");
 }
 
 public void make(string name) {
 system.out.println("制作" + name);
 }
}

在切面類中訪問連接點信息:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@aspect
public class joinpointaspect {
 
 @around("within(net.deniro.spring4.aspectj.cooka)")
 public void test(proceedingjoinpoint pjp) throws throwable {
 system.out.println("---------獲取連接點對象【開始】---------");
 system.out.println("參數(shù):" + pjp.getargs()[0]);
 system.out.println("簽名對象:" + pjp.gettarget().getclass());
 
 //執(zhí)行目標(biāo)對象方法
 pjp.proceed();
 system.out.println("---------獲取連接點對象【結(jié)束】---------");
 
 }
}

spring bean 配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
 
 <!--aspectj 驅(qū)動器 -->
 <aop:aspectj-autoproxy/>
 
 <bean id="cooka" class="net.deniro.spring4.aspectj.cooka"/>
 <bean class="net.deniro.spring4.aspectj.joinpointaspect"/>
</beans>

輸出結(jié)果:

---------獲取連接點對象【開始】---------
參數(shù):壽司
簽名對象:class net.deniro.spring4.aspectj.cooka
制作壽司
---------獲取連接點對象【結(jié)束】---------

5 綁定連接點的方法入?yún)?/strong>

args()、this()、target()、@args()、@within()、@target() 和 @annotation() 這些切點函數(shù)除可以指定類名外,還可以指定參數(shù)名,將目標(biāo)對象連接點上的方法入?yún)⒔壎ǖ皆鰪姷姆椒ㄖ?。 其中 args() 用于綁定連接點方法的入?yún)ⅲ?@annotation() 用于綁定連接點方法的注解對象,而 @args() 用于綁定連接點方法入?yún)⒌淖⒔狻?/p>

cookc 類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class cookc implements cook {
 public void make() {
 system.out.println("制作食品");
 }
 
 public void make(string name) {
 system.out.println("制作" + name);
 }
 
 public void make(string name, int num) {
 system.out.println("制作" + name + " " + num + " 個");
 }
}

切面類:

?
1
2
3
4
5
6
7
8
9
10
11
12
@aspect
public class paramsaspect {
 
 @before("target(net.deniro.spring4.aspectj.cookc) && args(name,num,..)")
 public void test(string name,int num) {
 system.out.println("----------綁定連接點入?yún)ⅰ鹃_始】----------");
 system.out.println("name:" + name);
 system.out.println("num:" + num);
 system.out.println("----------綁定連接點入?yún)ⅰ窘Y(jié)束】----------");
 
 }
}
  • 這里的連接點表達(dá)式 args(name,num,..) 會先找到 name 與 num 的類型,從而生成真正的表達(dá)式 args(string,int,..)。
  • 增強方法可以通過 name 與 num 得到連接點的方法入?yún)ⅰ?/li>

切點匹配和參數(shù)綁定的過程是這樣的:

  1. args()會根據(jù)參數(shù)名稱在增強方法中查到名稱相同的入?yún)⒉@得對應(yīng)參數(shù)的類型,這樣就得到了匹配連接點方法的入?yún)㈩愋?。
  2. 連接點方法入?yún)㈩愋退诘奈恢糜蓞?shù)名在 args() 函數(shù)中聲明的位置決定 。

上述示例中的匹配過程如下:

談?wù)凷pring AOP中@Aspect的高級用法示例

spring 配置:

?
1
2
3
4
5
<!--aspectj 驅(qū)動器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
 
<bean id="cookc" class="net.deniro.spring4.aspectj.cookc"/>
<bean class="net.deniro.spring4.aspectj.paramsaspect"/>

注意: 這里必須通過 <aop:aspectj-autoproxy proxy-target-class="true" />來啟用 cglib 動態(tài)代理,這是因為 cookc 的 public void make(string name, int num) 是該類獨有的方法(非接口定義的方法),所以必須使用 cglib 生成子類的代理方法 。

單元測試:

?
1
2
3
applicationcontext context = new classpathxmlapplicationcontext("spring-beans.xml");
cookc cookc = (cookc) context.getbean("cookc");
cookc.make("壽司", 100);

輸出結(jié)果:

----------綁定連接點入?yún)ⅰ鹃_始】----------
name:壽司
num:100
----------綁定連接點入?yún)ⅰ窘Y(jié)束】----------
制作壽司 100 個

6 綁定代理對象

使用 this() 或 target() 可綁定被代理對象的實例。通過類實例名綁定對象時,依然具有原來連接點匹配的功能,只是類名是由增強方法中的同名入?yún)㈩愋烷g接決定的。

?
1
2
3
4
5
6
7
8
9
10
@aspect
public class proxyaspect {
 
 @before("this(cook)")
 public void bind(cook cook) {
  system.out.println("--------綁定代理對象【開始】--------");
  system.out.println(cook.getclass().getname());
  system.out.println("--------綁定代理對象【結(jié)束】--------");
 }
}

首先通過 public void bind(cook cook) 找出 cook 所對應(yīng)的類型,接著轉(zhuǎn)換切點表達(dá)式為 this(net.deniro.spring4.aspectj.cook) 。這樣就表示該切點匹配所有代理對象為 cook 類中的所有方法。

輸出結(jié)果:

--------綁定代理對象【開始】--------
net.deniro.spring4.aspectj.cookc$$enhancerbyspringcglib$$217fb793
--------綁定代理對象【結(jié)束】--------

target() 綁定與 this() 相似。

7 綁定類注解對象

@within() 和 @target() 函數(shù)都可以將目標(biāo)類的注解對象綁定到增強方法中。

定義一個日志注解類:

?
1
2
3
4
5
@retention(retentionpolicy.runtime)//保留期限
@target({elementtype.method,elementtype.type})//目標(biāo)類型
public @interface log {
 boolean value() default true;//聲明成員變量
}

把該注解類應(yīng)用于 cookd:

?
1
2
3
4
5
6
7
8
9
10
@log
public class cookd implements cook {
 public void make() {
  system.out.println("制作糕點");
 }
 
 public void make(string name) {
 
 }
}

綁定類注解對象:

?
1
2
3
4
5
6
7
8
9
10
@aspect
public class classannotationobjectaspect {
 
 @before("@within(log)")
 public void bind(log log){
  system.out.println("----------綁定類注解對象【開始】----------");
  system.out.println(log.getclass().getname());
  system.out.println("----------綁定類注解對象【結(jié)束】----------");
 }
}

spring 配置:

?
1
2
3
4
5
6
<!--aspectj 驅(qū)動器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
 
 
<bean id="cookd" class="net.deniro.spring4.aspectj.cookd"/>
<bean class="net.deniro.spring4.aspectj.classannotationobjectaspect"/>

單元測試:

?
1
2
3
applicationcontext context = new classpathxmlapplicationcontext("spring-beans.xml");
cookd cook = (cookd) context.getbean("cookd");
cook.make();

輸出結(jié)果:

----------綁定類注解對象【開始】----------
com.sun.proxy.$proxy8
----------綁定類注解對象【結(jié)束】----------

從輸出結(jié)果  com.sun.proxy.$proxy8 可以看出 ,cookd 類的注解 log 對象也被代理咯o(∩_∩)o哈哈~

8 綁定返回值

在后置增強中,可以通過 returning 來綁定連接點方法的返回值。

切面:

?
1
2
3
4
5
6
7
8
9
10
@aspect
public class returnvalueaspect {
 
 @afterreturning(value = "target(net.deniro.spring4.aspectj.cooka)", returning = "value")
 public void bind(boolean value) {
  system.out.println("綁定返回值【開始】");
  system.out.println("value:" + value);
  system.out.println("綁定返回值【結(jié)束】");
 }
}

注意:returning 的值必須與方法參數(shù)名相同。

cooka 新增 smell 方法:

?
1
2
3
4
public boolean smell(string name) {
 system.out.println(name + "香嗎?");
 return true;
}

單元測試:

?
1
2
3
applicationcontext context = new classpathxmlapplicationcontext("spring-beans.xml");
cooka cook = (cooka) context.getbean("cooka");
cook.smell("烤鴨");

輸出結(jié)果:

烤鴨香嗎?
綁定返回值【開始】
value:true
綁定返回值【結(jié)束】

9 綁定異常

可以使用 afterthrowing 注解的 throwing 成員變量來綁定連接點拋出的異常。

切面類:

?
1
2
3
4
5
6
7
8
9
10
@aspect
public class exceptionaspect {
 
 @afterthrowing(value = "target(net.deniro.spring4.aspectj.cooka)",throwing = "e")
 public void bind(cookexception e){
  system.out.println("綁定異常【開始】");
  system.out.println("e:" + e.getmessage());
  system.out.println("綁定異常【結(jié)束】");
 }
}

注意:throwing 的值必須與方法參數(shù)名相同。

單元測試:

?
1
2
3
applicationcontext context = new classpathxmlapplicationcontext("spring-beans.xml");
cooka cook = (cooka) context.getbean("cooka");
cook.make("");

輸出結(jié)果:

綁定異常【開始】
e:煮啥呢???
綁定異常【結(jié)束】

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。

原文鏈接:https://www.jianshu.com/p/0d7cf0aeb338

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 男女精品视频 | 校花在公车上被内射好舒服 | 超h 超重口 高h 污肉1v1 | 厨房高h | 四虎1515hhc0m | 国产短视频精品一区二区三区 | 久久精品观看 | 晓雪老师我要进你里面好爽 | 草草视频在线观看 | 成年视频在线观看免费 | 我与肥熟老妇的性事 | 九九九九九九精品免费 | freexxxx性护士第一次 | 九九九久久久 | 大肥臀风间由美 中文字幕 大东北chinesexxxx露脸 | 99在线免费观看 | 欧美久久热 | www.久久精品视频 | 国产一级在线观看视频 | 久久久精品免费免费直播 | 俄罗斯freeⅹ性欧美 | 国产精品极品美女自在线 | sex5·性屋娱乐 | xxxxxx国产精品视频 | 国产高清自拍 | 高h孕交| 四虎影在线永久免费观看 | 草逼视频免费看 | 996免费视频国产在线播放 | 国产高清视频网站 | 精品午夜寂寞影院在线观看 | 夫妻性生活影院 | 精品一区二区三区视频日产 | 国产成人精品免费久久久久 | www.伊人| 亚洲国产成人资源在线桃色 | 性关系视频免费网站在线观看 | xxxxx性13一14| 精品国语国产在线对白 | 国内自拍2020 | 精品亚洲欧美中文字幕在线看 |