亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

spring中AOP 注解開(kāi)發(fā)示例詳解

 更新時(shí)間:2017年02月16日 08:35:40   作者:橘子不酸  
這篇文章主要介紹了spring中AOP注解開(kāi)發(fā)的相關(guān)資料,文中介紹的很詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。

一、簡(jiǎn)介

AOP主要包含了通知、切點(diǎn)和連接點(diǎn)等術(shù)語(yǔ),介紹如下:

通知(advice)

通知定義了切面是什么以及何時(shí)調(diào)用,何時(shí)調(diào)用包含以下幾種

  • Before 在方法被調(diào)用之前調(diào)用通知
  • After 在方法完成之后調(diào)用通知,無(wú)論方法執(zhí)行是否成功
  • After-returning 在方法成功執(zhí)行之后調(diào)用通知
  • After-throwing 在方法拋出異常后調(diào)用通知
  • Around 通知包裹了被通知的方法,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為

切點(diǎn)(PointCut)

通知定義了切面的什么和何時(shí),切點(diǎn)定義了何處,切點(diǎn)的定義會(huì)匹配通知所要織入的一個(gè)或多個(gè)連接點(diǎn),
我們通常使用明確的類(lèi)的方法名稱(chēng)來(lái)指定這些切點(diǎn),或是利用正則表達(dá)式定義匹配的類(lèi)和方法名稱(chēng)來(lái)指定這些切點(diǎn)。

連接點(diǎn)(JoinPoint)

連接點(diǎn)是在應(yīng)用執(zhí)行過(guò)程中能夠插入切面的一個(gè)點(diǎn),這個(gè)點(diǎn)可以是調(diào)用方法時(shí),拋出異常時(shí),甚至是修改一個(gè)字段時(shí),
切面代碼可以利用這些連接點(diǎn)插入到應(yīng)用的正常流程中,并添加新的行為,如日志、安全、事務(wù)、緩存等。

  • joinPoint.getSignature().getDeclaringTypeName() 可以獲取到調(diào)用方法的類(lèi)名(包括包名),
  • joinPoint.getSignature().getName()    可以獲取方法名,
  • Arrays.toString(joinPoint.getArgs())   得到的是方法調(diào)用的參數(shù)列表,
  • joinPoint.proceed()   可以得到方法的返回結(jié)果

二、注解開(kāi)發(fā)

聲明一個(gè)切面,只需要在類(lèi)名上添加@Aspect屬性即可,具體的連接點(diǎn),我們用@Pointcut和@Before、@After等標(biāo)注。
在聲明前 我們需要依賴(lài)配置pom

<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjrt</artifactId>
 <version>1.6.11</version>
</dependency>
<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.6.11</version>
</dependency>

例子

package com.ganji.demo.service.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Service;
/**
 * Created by admin on 2015/9/2.
 */
@Aspect
@Service
public class XmlAopDemoUserLog {
// 配置切點(diǎn) 及要傳的參數(shù) 
 @Pointcut("execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..)) && args(id)")
 public void pointCut(int id)
 {
 }
// 配置連接點(diǎn) 方法開(kāi)始執(zhí)行時(shí)通知
 @Before("pointCut(id)")
 public void beforeLog(int id) {
  System.out.println("開(kāi)始執(zhí)行前置通知 日志記錄:"+id);
 }
// 方法執(zhí)行完后通知
 @After("pointCut(id)")
 public void afterLog(int id) {
  System.out.println("開(kāi)始執(zhí)行后置通知 日志記錄:"+id);
 }
// 執(zhí)行成功后通知
 @AfterReturning("pointCut(id)")
 public void afterReturningLog(int id) {
  System.out.println("方法成功執(zhí)行后通知 日志記錄:"+id);
 }
// 拋出異常后通知
 @AfterThrowing("pointCut(id)")
 public void afterThrowingLog(int id) {
  System.out.println("方法拋出異常后執(zhí)行通知 日志記錄"+id);
 }
// 環(huán)繞通知
 @Around("pointCut(id)")
 public Object aroundLog(ProceedingJoinPoint joinpoint,int id) {
  Object result = null;
  try {
   System.out.println("環(huán)繞通知開(kāi)始 日志記錄"+id);
   long start = System.currentTimeMillis();
   //有返回參數(shù) 則需返回值
   result = joinpoint.proceed();
   long end = System.currentTimeMillis();
   System.out.println("總共執(zhí)行時(shí)長(zhǎng)" + (end - start) + " 毫秒");
   System.out.println("環(huán)繞通知結(jié)束 日志記錄");
  } catch (Throwable t) {
   System.out.println("出現(xiàn)錯(cuò)誤");
  }
  return result;
 }
}

AOP切面中的同步問(wèn)題

在WebLogAspect切面中,分別通過(guò)doBefore和doAfterReturning兩個(gè)獨(dú)立函數(shù)實(shí)現(xiàn)了切點(diǎn)頭部和切點(diǎn)返回后執(zhí)行的內(nèi)容,
若我們想統(tǒng)計(jì)請(qǐng)求的處理時(shí)間,就需要在doBefore處記錄時(shí)間,并在doAfterReturning處通過(guò)當(dāng)前時(shí)間與開(kāi)始處記錄的時(shí)間計(jì)算
得到請(qǐng)求處理的消耗時(shí)間。

那么我們是否可以在WebLogAspect切面中定義一個(gè)成員變量來(lái)給doBefore和doAfterReturning一起訪(fǎng)問(wèn)呢?是否會(huì)有同步問(wèn)題呢?

的確,直接在這里定義基本類(lèi)型會(huì)有同步問(wèn)題,所以我們可以引入ThreadLocal對(duì)象,像下面這樣進(jìn)行記錄:

@Aspect
@Component
public class WebLogAspect {
 private Logger logger = Logger.getLogger(getClass());
 ThreadLocal<Long> startTime = new ThreadLocal<>();
 @Pointcut("execution(public * com.juzi.web..*.*(..))")
 public void webLog(){}
 @Before("webLog()")
 public void doBefore(JoinPoint joinPoint) throws Throwable {
  startTime.set(System.currentTimeMillis());
  // 省略日志記錄內(nèi)容
 }
 @AfterReturning(returning = "ret", pointcut = "webLog()")
 public void doAfterReturning(Object ret) throws Throwable {
  // 處理完請(qǐng)求,返回內(nèi)容
  logger.info("RESPONSE : " + ret);
  logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
 }
}

AOP切面的優(yōu)先級(jí)

由于通過(guò)AOP實(shí)現(xiàn),程序得到了很好的解耦,但是也會(huì)帶來(lái)一些問(wèn)題,比如:我們可能會(huì)對(duì)Web層做多個(gè)切面,校驗(yàn)用戶(hù),
校驗(yàn)頭信息等等,這個(gè)時(shí)候經(jīng)常會(huì)碰到切面的處理順序問(wèn)題。

所以,我們需要定義每個(gè)切面的優(yōu)先級(jí),我們需要@Order(i)注解來(lái)標(biāo)識(shí)切面的優(yōu)先級(jí)。i的值越小,優(yōu)先級(jí)越高。
假設(shè)我們還有一個(gè)切面是CheckNameAspect用來(lái)校驗(yàn)name必須為didi,我們?yōu)槠湓O(shè)置@Order(10),
而上文中WebLogAspect設(shè)置為@Order(5),所以WebLogAspect有更高的優(yōu)先級(jí),這個(gè)時(shí)候執(zhí)行順序是這樣的:

在@Before中優(yōu)先執(zhí)行@Order(5)的內(nèi)容,再執(zhí)行@Order(10)的內(nèi)容

在@After和@AfterReturning中優(yōu)先執(zhí)行@Order(10)的內(nèi)容,再執(zhí)行@Order(5)的內(nèi)容

所以我們可以這樣子總結(jié):

  1. 在切入點(diǎn)前的操作,按order的值由小到大執(zhí)行
  2. 在切入點(diǎn)后的操作,按order的值由大到小執(zhí)行

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。

相關(guān)文章

  • springboot+dynamicDataSource動(dòng)態(tài)添加切換數(shù)據(jù)源方式

    springboot+dynamicDataSource動(dòng)態(tài)添加切換數(shù)據(jù)源方式

    這篇文章主要介紹了springboot+dynamicDataSource動(dòng)態(tài)添加切換數(shù)據(jù)源方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 談?wù)勀憧赡懿⒉涣私獾膉ava枚舉

    談?wù)勀憧赡懿⒉涣私獾膉ava枚舉

    這篇文章主要給大家介紹了一些關(guān)于你可能并不了解的java枚舉的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 你真的了解java單例模式了嗎?

    你真的了解java單例模式了嗎?

    這篇文章主要介紹了你真的了解java單例模式了嗎?實(shí)際上單例模式有著好幾個(gè)變種,并且多線(xiàn)程中涉及到線(xiàn)程安全問(wèn)題,,需要的朋友可以參考下
    2019-06-06
  • java Unicode和UTF-8之間轉(zhuǎn)換實(shí)例

    java Unicode和UTF-8之間轉(zhuǎn)換實(shí)例

    這篇文章主要介紹了java Unicode和UTF-8之間轉(zhuǎn)換實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • springBoot2.X配置全局捕獲異常的操作

    springBoot2.X配置全局捕獲異常的操作

    這篇文章主要介紹了springBoot2.X配置全局捕獲異常的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java精品項(xiàng)目瑞吉外賣(mài)之后端登錄功能篇

    Java精品項(xiàng)目瑞吉外賣(mài)之后端登錄功能篇

    這篇文章主要為大家詳細(xì)介紹了java精品項(xiàng)目-瑞吉外賣(mài)訂餐系統(tǒng),此項(xiàng)目過(guò)大,分為多章獨(dú)立講解,本篇內(nèi)容為后端登錄功能的實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Spring實(shí)戰(zhàn)之使用c:命名空間簡(jiǎn)化配置操作示例

    Spring實(shí)戰(zhàn)之使用c:命名空間簡(jiǎn)化配置操作示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用c:命名空間簡(jiǎn)化配置操作,結(jié)合實(shí)例形式詳細(xì)分析了Spring使用c:命名空間簡(jiǎn)化配置的相關(guān)接口與配置操作技巧,需要的朋友可以參考下
    2019-12-12
  • IDEA使用入門(mén)小白操作教程

    IDEA使用入門(mén)小白操作教程

    IntelliJ IDEA,就是Java語(yǔ)言開(kāi)發(fā)工具 (IDE) 功能與Eclipse同類(lèi)!本文通過(guò)圖文并茂的形式給大家介紹IntelliJ IDEA使用入門(mén)教程,非常適合新手小白操作,感興趣的朋友一起看看吧
    2020-10-10
  • SpringBoot項(xiàng)目打包成jar后獲取classpath下文件失敗的解決

    SpringBoot項(xiàng)目打包成jar后獲取classpath下文件失敗的解決

    這篇文章主要介紹了SpringBoot項(xiàng)目打包成jar后獲取classpath下文件失敗的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java 內(nèi)部類(lèi)的定義與范例

    Java 內(nèi)部類(lèi)的定義與范例

    說(shuō)起內(nèi)部類(lèi)這個(gè)詞,想必很多人都不陌生,但是又會(huì)覺(jué)得不熟悉。原因是平時(shí)編寫(xiě)代碼時(shí)可能用到的場(chǎng)景不多,用得最多的是在有事件監(jiān)聽(tīng)的情況下,并且即使用到也很少去總結(jié)內(nèi)部類(lèi)的用法。今天我們就來(lái)一探究竟
    2021-11-11

最新評(píng)論