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

服務(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教程 - 詳解SpringBoot之集成Spring AOP

詳解SpringBoot之集成Spring AOP

2020-11-26 14:33木葉之榮 Java教程

本篇文章主要介紹了詳解SpringBoot之集成Spring AOP,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

在開始之前,我們先把需要的jar包添加到工程里。新增maven依賴如下:

?
1
2
3
4
<dependency>
  <groupid>org.springframework.boot</groupid>
  <artifactid>spring-boot-starter-aop</artifactid>
</dependency>

 接下來,我們進(jìn)入正題。這里的涉及的通知類型有:前置通知、后置最終通知、后置返回通知、后置異常通知、環(huán)繞通知,下面我們就具體的來看一下怎么在springboot中添加這些通知。

首先我們先創(chuàng)建一個(gè)aspect切面類:

?
1
2
3
4
5
@component
@aspect
public class webcontrolleraop {
 
}

指定切點(diǎn):

?
1
2
3
4
5
//匹配com.zkn.learnspringboot.web.controller包及其子包下的所有類的所有方法
@pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
public void executeservice(){
 
}

接著我們再創(chuàng)建一個(gè)controller請求處理類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.zkn.learnspringboot.web.controller;
 
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.restcontroller;
 
/**
 * created by zkn on 2016/11/19.
 */
@restcontroller
@requestmapping("/aop")
public class aoptestcontroller {
 
}

前置通知

配置前置通知:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
 * 前置通知,方法調(diào)用前被調(diào)用
 * @param joinpoint
 */
@before("executeservice()")
public void dobeforeadvice(joinpoint joinpoint){
  system.out.println("我是前置通知!!!");
  //獲取目標(biāo)方法的參數(shù)信息
  object[] obj = joinpoint.getargs();
  //aop代理類的信息
  joinpoint.getthis();
  //代理的目標(biāo)對象
  joinpoint.gettarget();
  //用的最多 通知的簽名
  signature signature = joinpoint.getsignature();
  //代理的是哪一個(gè)方法
  system.out.println(signature.getname());
  //aop代理類的名字
  system.out.println(signature.getdeclaringtypename());
  //aop代理類的類(class)信息
  signature.getdeclaringtype();
  //獲取requestattributes
  requestattributes requestattributes = requestcontextholder.getrequestattributes();
  //從獲取requestattributes中獲取httpservletrequest的信息
  httpservletrequest request = (httpservletrequest) requestattributes.resolvereference(requestattributes.reference_request);
  //如果要獲取session信息的話,可以這樣寫:
  //httpsession session = (httpsession) requestattributes.resolvereference(requestattributes.reference_session);
  enumeration<string> enumeration = request.getparameternames();
  map<string,string> parametermap = maps.newhashmap();
  while (enumeration.hasmoreelements()){
    string parameter = enumeration.nextelement();
    parametermap.put(parameter,request.getparameter(parameter));
  }
  string str = json.tojsonstring(parametermap);
  if(obj.length > 0) {
    system.out.println("請求的參數(shù)信息為:"+str);
  }
}

注意:這里用到了joinpoint和requestcontextholder。通過joinpoint可以獲得通知的簽名信息,如目標(biāo)方法名、目標(biāo)方法參數(shù)信息等。通過requestcontextholder來獲取請求信息,session信息。

接下來我們在controller類里添加一個(gè)請求處理方法來測試一下前置通知:

?
1
2
3
4
5
@requestmapping("/testbeforeservice.do")
public string testbeforeservice(string key,string value){
 
  return "key="+key+" value="+value;
}

前置通知攔截結(jié)果如下所示:

詳解SpringBoot之集成Spring AOP

后置返回通知

配置后置返回通知的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * 后置返回通知
 * 這里需要注意的是:
 *   如果參數(shù)中的第一個(gè)參數(shù)為joinpoint,則第二個(gè)參數(shù)為返回值的信息
 *   如果參數(shù)中的第一個(gè)參數(shù)不為joinpoint,則第一個(gè)參數(shù)為returning中對應(yīng)的參數(shù)
 * returning 限定了只有目標(biāo)方法返回值與通知方法相應(yīng)參數(shù)類型時(shí)才能執(zhí)行后置返回通知,否則不執(zhí)行,對于returning對應(yīng)的通知方法參數(shù)為object類型將匹配任何目標(biāo)返回值
 * @param joinpoint
 * @param keys
 */
@afterreturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys")
public void doafterreturningadvice1(joinpoint joinpoint,object keys){
 
  system.out.println("第一個(gè)后置返回通知的返回值:"+keys);
}
 
@afterreturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argnames = "keys")
public void doafterreturningadvice2(string keys){
 
  system.out.println("第二個(gè)后置返回通知的返回值:"+keys);
}

controller里添加響應(yīng)的請求處理信息來測試后置返回通知:

?
1
2
3
4
5
6
7
8
9
10
@requestmapping("/testafterreturning.do")
public string testafterreturning(string key){
 
  return "key=: "+key;
}
@requestmapping("/testafterreturning01.do")
public integer testafterreturning01(integer key){
 
  return key;
}

當(dāng)發(fā)送請求為:http://localhost:8001/aop/testafterreturning.do?key=testsss&value=855sss時(shí),處理結(jié)果如圖所示:

詳解SpringBoot之集成Spring AOP

當(dāng)發(fā)送請求為:http://localhost:8001/aop/testafterreturning01.do?key=55553&value=855sss時(shí),處理結(jié)果如圖所示:

詳解SpringBoot之集成Spring AOP

后置異常通知

后置異常通知的配置方式如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * 后置異常通知
 * 定義一個(gè)名字,該名字用于匹配通知實(shí)現(xiàn)方法的一個(gè)參數(shù)名,當(dāng)目標(biāo)方法拋出異常返回后,將把目標(biāo)方法拋出的異常傳給通知方法;
 * throwing 限定了只有目標(biāo)方法拋出的異常與通知方法相應(yīng)參數(shù)異常類型時(shí)才能執(zhí)行后置異常通知,否則不執(zhí)行,
 *   對于throwing對應(yīng)的通知方法參數(shù)為throwable類型將匹配任何異常。
 * @param joinpoint
 * @param exception
 */
@afterthrowing(value = "executeservice()",throwing = "exception")
public void doafterthrowingadvice(joinpoint joinpoint,throwable exception){
  //目標(biāo)方法名:
  system.out.println(joinpoint.getsignature().getname());
  if(exception instanceof nullpointerexception){
    system.out.println("發(fā)生了空指針異常!!!!!");
  }
}

controller里配置響應(yīng)的請求處理類:

?
1
2
3
4
5
@requestmapping("/testafterthrowing.do")
public string testafterthrowing(string key){
 
  throw new nullpointerexception();
}

后置異常通知方法的處理結(jié)果如下所示:

詳解SpringBoot之集成Spring AOP

后置最終通知

后置最終通知的配置方式如下:

?
1
2
3
4
5
6
7
8
9
/**
 * 后置最終通知(目標(biāo)方法只要執(zhí)行完了就會(huì)執(zhí)行后置通知方法)
 * @param joinpoint
 */
@after("executeservice()")
public void doafteradvice(joinpoint joinpoint){
 
  system.out.println("后置通知執(zhí)行了!!!!");
}

controller類配置相應(yīng)的請求處理類:

?
1
2
3
4
5
6
7
8
9
10
@requestmapping("/testafter.do")
public string testafter(string key){
 
  throw new nullpointerexception();
}
@requestmapping("/testafter02.do")
public string testafter02(string key){
 
  return key;
}

當(dāng)發(fā)送請求為:http://localhost:8001/aop/testafter.do?key=55553&value=855sss

詳解SpringBoot之集成Spring AOP

當(dāng)發(fā)送請求為:http://localhost:8001/aop/testafter02.do?key=55553&value=855sss

詳解SpringBoot之集成Spring AOP

環(huán)繞通知

環(huán)繞通知的配置方式如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * 環(huán)繞通知:
 *  環(huán)繞通知非常強(qiáng)大,可以決定目標(biāo)方法是否執(zhí)行,什么時(shí)候執(zhí)行,執(zhí)行時(shí)是否需要替換方法參數(shù),執(zhí)行完畢是否需要替換返回值。
 *  環(huán)繞通知第一個(gè)參數(shù)必須是org.aspectj.lang.proceedingjoinpoint類型
 */
@around("execution(* com.zkn.learnspringboot.web.controller..*.testaround*(..))")
public object doaroundadvice(proceedingjoinpoint proceedingjoinpoint){
  system.out.println("環(huán)繞通知的目標(biāo)方法名:"+proceedingjoinpoint.getsignature().getname());
  try {
    object obj = proceedingjoinpoint.proceed();
    return obj;
  } catch (throwable throwable) {
    throwable.printstacktrace();
  }
  return null;
}

controller對應(yīng)的請求處理類如下:

?
1
2
3
4
5
@requestmapping("/testaroundservice.do")
public string testaroundservice(string key){
 
  return "環(huán)繞通知:"+key;
}

當(dāng)發(fā)送請求為:http://localhost:8001/aop/testaroundservice.do?key=55553

詳解SpringBoot之集成Spring AOP

當(dāng)發(fā)送請求為:http://localhost:8001/aop/testafter02.do?key=55553&value=855sss時(shí),不符合環(huán)繞通知的切入規(guī)則,所以環(huán)繞通知不會(huì) 執(zhí)行。

完整的aop配置代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package com.zkn.learnspringboot.aop;
 
import com.alibaba.fastjson.json;
import com.google.common.collect.maps;
import org.aspectj.lang.joinpoint;
import org.aspectj.lang.proceedingjoinpoint;
import org.aspectj.lang.signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.component;
import org.springframework.web.context.request.requestattributes;
import org.springframework.web.context.request.requestcontextholder;
 
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpsession;
import java.util.enumeration;
import java.util.map;
 
/**
 * created by zkn on 2016/11/18.
 */
@component
@aspect
public class webcontrolleraop {
 
  //匹配com.zkn.learnspringboot.web.controller包及其子包下的所有類的所有方法
  @pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
  public void executeservice(){
 
  }
 
  /**
   * 前置通知,方法調(diào)用前被調(diào)用
   * @param joinpoint
   */
  @before("executeservice()")
  public void dobeforeadvice(joinpoint joinpoint){
    system.out.println("我是前置通知!!!");
    //獲取目標(biāo)方法的參數(shù)信息
    object[] obj = joinpoint.getargs();
    //aop代理類的信息
    joinpoint.getthis();
    //代理的目標(biāo)對象
    joinpoint.gettarget();
    //用的最多 通知的簽名
    signature signature = joinpoint.getsignature();
    //代理的是哪一個(gè)方法
    system.out.println(signature.getname());
    //aop代理類的名字
    system.out.println(signature.getdeclaringtypename());
    //aop代理類的類(class)信息
    signature.getdeclaringtype();
    //獲取requestattributes
    requestattributes requestattributes = requestcontextholder.getrequestattributes();
    //從獲取requestattributes中獲取httpservletrequest的信息
    httpservletrequest request = (httpservletrequest) requestattributes.resolvereference(requestattributes.reference_request);
    //如果要獲取session信息的話,可以這樣寫:
    //httpsession session = (httpsession) requestattributes.resolvereference(requestattributes.reference_session);
    enumeration<string> enumeration = request.getparameternames();
    map<string,string> parametermap = maps.newhashmap();
    while (enumeration.hasmoreelements()){
      string parameter = enumeration.nextelement();
      parametermap.put(parameter,request.getparameter(parameter));
    }
    string str = json.tojsonstring(parametermap);
    if(obj.length > 0) {
      system.out.println("請求的參數(shù)信息為:"+str);
    }
  }
 
  /**
   * 后置返回通知
   * 這里需要注意的是:
   *   如果參數(shù)中的第一個(gè)參數(shù)為joinpoint,則第二個(gè)參數(shù)為返回值的信息
   *   如果參數(shù)中的第一個(gè)參數(shù)不為joinpoint,則第一個(gè)參數(shù)為returning中對應(yīng)的參數(shù)
   * returning 限定了只有目標(biāo)方法返回值與通知方法相應(yīng)參數(shù)類型時(shí)才能執(zhí)行后置返回通知,否則不執(zhí)行,對于returning對應(yīng)的通知方法參數(shù)為object類型將匹配任何目標(biāo)返回值
   * @param joinpoint
   * @param keys
   */
  @afterreturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys")
  public void doafterreturningadvice1(joinpoint joinpoint,object keys){
 
    system.out.println("第一個(gè)后置返回通知的返回值:"+keys);
  }
 
  @afterreturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argnames = "keys")
  public void doafterreturningadvice2(string keys){
 
    system.out.println("第二個(gè)后置返回通知的返回值:"+keys);
  }
 
  /**
   * 后置異常通知
   * 定義一個(gè)名字,該名字用于匹配通知實(shí)現(xiàn)方法的一個(gè)參數(shù)名,當(dāng)目標(biāo)方法拋出異常返回后,將把目標(biāo)方法拋出的異常傳給通知方法;
   * throwing 限定了只有目標(biāo)方法拋出的異常與通知方法相應(yīng)參數(shù)異常類型時(shí)才能執(zhí)行后置異常通知,否則不執(zhí)行,
   *   對于throwing對應(yīng)的通知方法參數(shù)為throwable類型將匹配任何異常。
   * @param joinpoint
   * @param exception
   */
  @afterthrowing(value = "executeservice()",throwing = "exception")
  public void doafterthrowingadvice(joinpoint joinpoint,throwable exception){
    //目標(biāo)方法名:
    system.out.println(joinpoint.getsignature().getname());
    if(exception instanceof nullpointerexception){
      system.out.println("發(fā)生了空指針異常!!!!!");
    }
  }
 
  /**
   * 后置最終通知(目標(biāo)方法只要執(zhí)行完了就會(huì)執(zhí)行后置通知方法)
   * @param joinpoint
   */
  @after("executeservice()")
  public void doafteradvice(joinpoint joinpoint){
 
    system.out.println("后置通知執(zhí)行了!!!!");
  }
 
  /**
   * 環(huán)繞通知:
   *  環(huán)繞通知非常強(qiáng)大,可以決定目標(biāo)方法是否執(zhí)行,什么時(shí)候執(zhí)行,執(zhí)行時(shí)是否需要替換方法參數(shù),執(zhí)行完畢是否需要替換返回值。
   *  環(huán)繞通知第一個(gè)參數(shù)必須是org.aspectj.lang.proceedingjoinpoint類型
   */
  @around("execution(* com.zkn.learnspringboot.web.controller..*.testaround*(..))")
  public object doaroundadvice(proceedingjoinpoint proceedingjoinpoint){
    system.out.println("環(huán)繞通知的目標(biāo)方法名:"+proceedingjoinpoint.getsignature().getname());
    try {//obj之前可以寫目標(biāo)方法執(zhí)行前的邏輯
      object obj = proceedingjoinpoint.proceed();//調(diào)用執(zhí)行目標(biāo)方法
      return obj;
    } catch (throwable throwable) {
      throwable.printstacktrace();
    }
    return null;
  }
}

完整的controller類代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.zkn.learnspringboot.web.controller;
 
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.restcontroller;
 
/**
 * created by zkn on 2016/11/19.
 */
@restcontroller
@requestmapping("/aop")
public class aoptestcontroller {
 
  @requestmapping("/testbeforeservice.do")
  public string testbeforeservice(string key,string value){
 
    return "key="+key+" value="+value;
  }
  @requestmapping("/testafterreturning.do")
  public string testafterreturning(string key){
 
    return "key=: "+key;
  }
  @requestmapping("/testafterreturning01.do")
  public integer testafterreturning01(integer key){
 
    return key;
  }
  @requestmapping("/testafterthrowing.do")
  public string testafterthrowing(string key){
 
    throw new nullpointerexception();
  }
  @requestmapping("/testafter.do")
  public string testafter(string key){
 
    throw new nullpointerexception();
  }
  @requestmapping("/testafter02.do")
  public string testafter02(string key){
 
    return key;
  }
  @requestmapping("/testaroundservice.do")
  public string testaroundservice(string key){
 
    return "環(huán)繞通知:"+key;
  }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://blog.csdn.net/zknxx/article/details/53240959

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 大吊小说 | 国产99热| 天堂激情网 | 亚洲欧洲日产v特级毛片 | 暖暖日本高清 | 男男双性生子产乳高辣h | 国产精品视频一区二区三区不卡 | 美女被吸乳老师羞羞漫画 | 免费草比视频 | 春色视频网站 | 日本妇人成熟免费观看18 | a级片在线观看免费 | 国产品精人成福利视频 | 草草草草视频 | 免费的伦理片 | 美女尿口照片 | 日本网络视频www色高清免费 | 日韩在线天堂免费观看 | 欧美三级小说 | 女性性色生活片免费观看 | 国产精品久久久久这里只有精品 | 欧美日韩国产成人精品 | 动漫人物差差插曲漫画 | 久久视频在线视频 | 久久亚洲精品中文字幕60分钟 | 久久国产主播福利在线 | 亚洲区精品久久一区二区三区 | 32pao强力打造免费高速高清 | 国产激情久久久久影院小草 | 被老外玩爽的中国美女视频 | 人人揉揉香蕉 | 精品欧美| 色悠久久久久综合欧美99 | 日本福利片国产午夜久久 | 国产无套在线播放 | 性色AV乱码一区二区三区视频 | 国产日韩欧美 | 国产日日操 | 亚洲男人天堂网址 | 亚洲国产精品第一区二区三区 | 亚洲第成色999久久网站 |