aop

https://juejin.cn/post/6844903720203862023
https://blog.51cto.com/u_15155081/2720729

package com.yangxin.core.transaction;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class TransactionDemo2 {
    
    @Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")
    public void point(){
        
    }
    
    @Before(value="point()")
    public void before(){
        System.out.println("transaction begin");
    }
    
    @AfterReturning(value = "point()")
    public void after(){
        System.out.println("transaction commit");
    }
    
    @Around("point()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("transaction begin");
        joinPoint.proceed();
        System.out.println("transaction commit");
        
    }
}

切面(Aspect):是一個(gè)類殿衰,里面定義了通知與切點(diǎn)罐脊。

切點(diǎn)(PointCut):表達(dá)式瞎嬉。就是告訴程序要在執(zhí)行哪些核心業(yè)務(wù)的時(shí)候唐片,執(zhí)行非核心的業(yè)務(wù)。

通知(advice):五種通知方式:
@Before:前置通知柠掂,在調(diào)用目標(biāo)方法之前執(zhí)行通知定義的任務(wù)
@After:后置通知项滑,在目標(biāo)方法執(zhí)行結(jié)束后,無(wú)論執(zhí)行結(jié)果如何都執(zhí)行通知定義的任務(wù)
@After-returning:后置通知涯贞,在目標(biāo)方法執(zhí)行結(jié)束后枪狂,如果執(zhí)行成功,則執(zhí)行通知定義的任務(wù)
@After-throwing:異常通知肩狂,如果目標(biāo)方法執(zhí)行過(guò)程中拋出異常摘完,則執(zhí)行通知定義的任務(wù)
@Around:環(huán)繞通知,在目標(biāo)方法執(zhí)行前和執(zhí)行后傻谁,都需要執(zhí)行通知定義的任務(wù)。
連接點(diǎn)(Join point)
??連接點(diǎn)是在應(yīng)用執(zhí)行過(guò)程中能夠插入切面的一個(gè)點(diǎn)列粪。

<aop:aspectj-autoproxy/> 使用這個(gè)在springaop中開啟aspectJ注解
审磁、
1.通過(guò) @EnableAspectJAutoProxy解或者 XML 配置(
<aop:aspect-autoproxy>)可以激活 AOP 模塊谈飒,底層會(huì)注冊(cè)一個(gè) AbstractAutoProxyCreator 類型的 Bean 完成 AOP 自動(dòng)代理

2.Spring AOP 中的自動(dòng)代理主要由 AbstractAutoProxyCreator 這個(gè) Bean 進(jìn)行創(chuàng)建,因?yàn)樗鼘?shí)現(xiàn)了幾種 BeanPostProcessor态蒂,例如在 Bean 加載過(guò)程中杭措,初始化后會(huì)調(diào)用 AbstractAutoProxyCreator 的方法進(jìn)行處理,返回一個(gè)代理對(duì)象

這個(gè)地方存疑钾恢?:初始化的時(shí)候會(huì)引入其他的bean手素,解決bean的循環(huán)依賴的時(shí)候,三級(jí)緩存是可以生成代理對(duì)象瘩蚪,這個(gè)地方我覺得應(yīng)該是沒有循環(huán)依賴的在beanpostprocess.afterInitialization
之后實(shí)現(xiàn)泉懦,有依賴場(chǎng)景在初始化的時(shí)候進(jìn)行生成了
解決上面的疑問(wèn)

image.png

Spring AOP 自動(dòng)代理的實(shí)現(xiàn)主要由 AbstractAutoProxyCreator 完成,它實(shí)現(xiàn)了
BeanPostProcessor疹瘦、SmartInstantiationAwareBeanPostProcessor 和InstantiationAwareBeanPostProcessor
三個(gè)接口崩哩,那么這個(gè)類就是 Spring AOP 的入口,在這里將 Advice 織入我們的 Bean 中言沐,創(chuàng)建代理對(duì)象邓嘹。

image.png

三級(jí)緩存走的類依賴


123.png

image.png

需要記住的東西,必要為:warpIfnessary()

總結(jié)創(chuàng)建代理對(duì)象
通過(guò)1.getAdvicesAndAdvisorsForBean(),找出合適的advisor對(duì)象
2.通過(guò)createProxy()险胰,根據(jù)找到的advisor創(chuàng)建一個(gè)代理對(duì)象汹押,jdk動(dòng)態(tài)代理或者CGlib動(dòng)態(tài)代理
(這個(gè)createProxy就是在warpIfNessary中的方法)

設(shè)計(jì)模式使用:
super: 代理模式
1.策略模式:
createAopProxy

選擇是jdk動(dòng)態(tài)代理還是cglib代理

2.模板模式
子類實(shí)現(xiàn)具體的方法,父類實(shí)現(xiàn)模板方法


image.png

3.責(zé)任鏈模式:
具體處理者接到請(qǐng)求后起便,可以選擇將請(qǐng)求處理掉鲸阻,或者將請(qǐng)求傳給下家。由于具體處理者持有對(duì)下家的引用


image.png

4.適配器:
將目標(biāo)類和適配者類解耦缨睡,通過(guò)引入一個(gè)適配器類來(lái)重用現(xiàn)有的適配者類鸟悴,而無(wú)須修改原有代碼。

image.png

實(shí)現(xiàn):
1.全部通過(guò)xml實(shí)現(xiàn):
切面實(shí)現(xiàn)(log日志)

package com.lagou.edu.utils;

/**
 * @author 應(yīng)癲
 */

public class LogUtils {

  /**
   * 業(yè)務(wù)邏輯開始之前執(zhí)行
   */
  
  public void beforeMethod(JoinPoint joinPoint) {
     Object[] args = joinPoint.getArgs();
    for (int i = 0; i < args.length; i++) {
      Object arg = args[i];
      System.out.println(arg);
    }
    System.out.println("業(yè)務(wù)邏輯開始執(zhí)行之前執(zhí)行.......");
  }


  /**
   * 業(yè)務(wù)邏輯結(jié)束時(shí)執(zhí)行(無(wú)論異常與否)
   */

  public void afterMethod() {
    System.out.println("業(yè)務(wù)邏輯結(jié)束時(shí)執(zhí)行奖年,無(wú)論異常與否都執(zhí)行.......");
  }

  /**
   * 異常時(shí)時(shí)執(zhí)行
   */
  public void exceptionMethod() {
    System.out.println("異常時(shí)執(zhí)行.......");
  }

  /**
   * 業(yè)務(wù)邏輯正常時(shí)執(zhí)行
   */

  public void successMethod(Object retVal) {
    System.out.println("業(yè)務(wù)邏輯正常時(shí)執(zhí)行.......");
  }

}

public Object arroundMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    System.out.println("環(huán)繞通知中的beforemethod....");

    Object result = null;
    try{
      // 控制原有業(yè)務(wù)邏輯是否執(zhí)行
      // result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
    }catch(Exception e) {
      System.out.println("環(huán)繞通知中的exceptionmethod....");
    }finally {
      System.out.println("環(huán)繞通知中的after method....");
    }

    return result;
  }

1.設(shè)置bean
2.設(shè)置aop:config
指定切點(diǎn)<AOP:POINT> 指定通知 <AOP:BEFORE/AFTER/AROUND>

<!--進(jìn)行aop相關(guān)的xml配置,配置aop的過(guò)程其實(shí)就是把a(bǔ)op相關(guān)術(shù)語(yǔ)落地-->
  <!--橫切邏輯bean-->
<bean id="logUtils" class="com.lagou.edu.utils.LogUtils"></bean>
  <!--使用config標(biāo)簽表明開始aop配置,在內(nèi)部配置切面aspect-->

  <!--aspect  =  切入點(diǎn)(鎖定方法) + 方位點(diǎn)(鎖定方法中的特殊時(shí)機(jī))+ 橫切邏輯 -->
  <aop:config>
    <aop:aspect id="logAspect" ref="logUtils">

      <!--切入點(diǎn)鎖定我們感興趣的方法细诸,使用aspectj語(yǔ)法表達(dá)式-->
      <!--..參數(shù)中的兩個(gè)點(diǎn)表示可以有參數(shù),也可以沒有參數(shù)陋守,有的話也可以是任意類型震贵,參數(shù)中的 *表示參數(shù)可以是任意類型,但必須有參數(shù)水评。 -->
      <!--包名中的..兩個(gè)點(diǎn)表示中間可以是任意層-->
      <!--<aop:pointcut id="pt1" expression="execution(* *..*.*(..))"/>-->
     <aop:pointcut id="pt1" expression="execution(public void com.lagou.edu.service.impl.TransferServiceImpl.transfer(java.lang.String,java.lang.String,int))"/>

<!--      <aop:pointcut id="pt1" expression="execution(* com.lagou.edu.service.impl.TransferServiceImpl.*(..))"/>
-->
      <!--方位信息,pointcut-ref關(guān)聯(lián)切入點(diǎn)-->
      <!--aop:before前置通知/增強(qiáng)-->
      <aop:before method="beforeMethod" pointcut-ref="pt1"/>
      <!--aop:after猩系,最終通知,無(wú)論如何都執(zhí)行-->
      <!--aop:after-returnning中燥,正常執(zhí)行通知,retValue是接受方法的返回值的-->
      <aop:after-returning method="successMethod" returning="retValue"/>
      <!--aop:after-throwing寇甸,異常通知-->

      <aop:around method="arroundMethod" pointcut-ref="pt1"/>

    </aop:aspect>
  </aop:config>-->

二:通過(guò)純注解方式實(shí)現(xiàn):

package com.lagou.edu.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author 應(yīng)癲
 */
@Component
@Aspect
public class LogUtils {


  @Pointcut("execution(* com.lagou.edu.service.impl.TransferServiceImpl.*(..))")
  public void pt1(){

  }


  /**
   * 業(yè)務(wù)邏輯開始之前執(zhí)行
   */
  @Before("pt1()")
  public void beforeMethod(JoinPoint joinPoint) {
    Object[] args = joinPoint.getArgs();
    for (int i = 0; i < args.length; i++) {
      Object arg = args[i];
      System.out.println(arg);
    }
    System.out.println("業(yè)務(wù)邏輯開始執(zhí)行之前執(zhí)行.......");
  }


  /**
   * 業(yè)務(wù)邏輯結(jié)束時(shí)執(zhí)行(無(wú)論異常與否)
   */
  @After("pt1()")
  public void afterMethod() {
    System.out.println("業(yè)務(wù)邏輯結(jié)束時(shí)執(zhí)行,無(wú)論異常與否都執(zhí)行.......");
  }


  /**
   * 異常時(shí)時(shí)執(zhí)行
   */
  @AfterThrowing("pt1()")
  public void exceptionMethod() {
    System.out.println("異常時(shí)執(zhí)行.......");
  }


  /**
   * 業(yè)務(wù)邏輯正常時(shí)執(zhí)行
   */
  @AfterReturning(value = "pt1()",returning = "retVal")
  public void successMethod(Object retVal) {
    System.out.println("業(yè)務(wù)邏輯正常時(shí)執(zhí)行.......");
  }


  /**
   * 環(huán)繞通知
   *
   */
  /*@Around("pt1()")*/
  public Object arroundMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    System.out.println("環(huán)繞通知中的beforemethod....");

    Object result = null;
    try{
      // 控制原有業(yè)務(wù)邏輯是否執(zhí)行
      // result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
    }catch(Exception e) {
      System.out.println("環(huán)繞通知中的exceptionmethod....");
    }finally {
      System.out.println("環(huán)繞通知中的after method....");
    }

    return result;
  }

}

只需要在配置文件中增加一個(gè)配置項(xiàng)即可:

<!--開啟aop注解驅(qū)動(dòng)
   proxy-target-class:true強(qiáng)制使用cglib
 
 -->
 <aop:aspectj-autoproxy/>

甚至我們可以不使用xml文件
使用純注解
在啟動(dòng)類上加上

@EnableAspectJAutoProxy 
image.png

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拿霉,隨后出現(xiàn)的幾起案子吟秩,更是在濱河造成了極大的恐慌,老刑警劉巖绽淘,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涵防,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡沪铭,警方通過(guò)查閱死者的電腦和手機(jī)壮池,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)杀怠,“玉大人椰憋,你說(shuō)我怎么就攤上這事⊥匀猓” “怎么了熏矿?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)离钝。 經(jīng)常有香客問(wèn)我票编,道長(zhǎng),這世上最難降的妖魔是什么卵渴? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任慧域,我火速辦了婚禮,結(jié)果婚禮上浪读,老公的妹妹穿的比我還像新娘昔榴。我一直安慰自己,他們只是感情好碘橘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布互订。 她就那樣靜靜地躺著,像睡著了一般痘拆。 火紅的嫁衣襯著肌膚如雪仰禽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天纺蛆,我揣著相機(jī)與錄音吐葵,去河邊找鬼。 笑死桥氏,一個(gè)胖子當(dāng)著我的面吹牛温峭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播字支,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼凤藏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奸忽!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起清笨,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤月杉,失蹤者是張志新(化名)和其女友劉穎刃跛,沒想到半個(gè)月后抠艾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桨昙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年检号,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛙酪。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡齐苛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桂塞,到底是詐尸還是另有隱情凹蜂,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布阁危,位于F島的核電站玛痊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏狂打。R本人自食惡果不足惜擂煞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趴乡。 院中可真熱鬧对省,春花似錦、人聲如沸晾捏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惦辛。三九已至劳秋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間裙品,已是汗流浹背俗批。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留市怎,地道東北人岁忘。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像区匠,于是被迫代替她去往敵國(guó)和親干像。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帅腌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容