四、Spring的AOP

AOP實現(xiàn)可分為兩類(按AOP框架修改源代碼的時機):

  • 靜態(tài)AOP實現(xiàn):AOP框架在編譯階段對程序進行修改摄欲,即實現(xiàn)對目標類的增強轿亮,生成靜態(tài)的AOP代理類(生成的*.class文件已經(jīng)被改掉了,需要使用特定的編輯器)胸墙。以AspectJ為代表我注。
  • 動態(tài)AOP實現(xiàn):AOP框架在運行階段動態(tài)生成AOP代理(在內(nèi)存中以JDK動態(tài)代理或cglib動態(tài)代理生成AOP代理類)。以實現(xiàn)對目標類的增強迟隅。以Spring AOP為代表但骨。

AOP的基本概念:

AOP框架具有如下兩個特征:

  • 個步驟之間的良好隔離性励七。
  • 源代碼無關(guān)性。

關(guān)于面向切面編程的一些術(shù)語:

  • 切面(Aspect):切面用于組織多個Advice奔缠,Advice放在切面中定義呀伙。
  • 連接點(Joinpoint):程序執(zhí)行過程中明確的點,如方法的調(diào)用添坊,或者異常的拋出剿另。在Spring AOP中,連接點總是方法的調(diào)用贬蛙。
  • 增強處理(Advice):AOP框架在特定的點執(zhí)行的增強處理雨女。處理有“before”,“around”阳准,“after”等氛堕。
  • 切入點(Pointcut):可以插入增強處理的連接點。簡而言之野蝇,當某個連接點滿足指定要求時讼稚,該連接點將被添加增強處理,該連接點也就變成了切入點绕沈。
pointcut xxxPointcut():execution(void H*.say*())

如何使用表達式定義切入點是AOP的核心锐想,Spring默認使用AspectJ切入點語法:

  • 引入:將方法或字段添加到被處理的類中。Spring允許將新的接口引入到任何被處理的對象中乍狐。例如赠摇,你可以使用一個引入,使任何對象實現(xiàn)IsModified接口浅蚪,以此來簡化緩存藕帜。
  • 目標對象:被AOP框架進行增強處理的對象,也被稱為增強的對象惜傲。如果AOP框架采用的是動態(tài)AOP實現(xiàn)洽故,那么該對象就是一個被代理的對象。
  • AOP代理:AOP框架創(chuàng)建的對象盗誊,代理就是對目標對象的增強时甚。Spring中的AOP代理可以是JDK動態(tài)代理,也可以是cglib代理浊伙。前者為實現(xiàn)接口的目標對象的代理撞秋,后者不實現(xiàn)接口的目標對象的代理。
  • 織入(Weaving):將增強處理添加到目標對象中嚣鄙,并創(chuàng)建一個被增強的對象(AOP代理)的過程就是織入吻贿。植入有兩種實現(xiàn)方式---編譯時增強(如AspectJ)和運行時增強(如Spring AOP)。Spring和其他純Java AOP框架一樣哑子,在運行時完成織入舅列。

Spring的AOP支持:

Spring中的AOP代理由Spring的IOC容器負責生成肌割、管理,其依賴關(guān)系也由IOC容器負責管理帐要。AOP代理可以直接使用容器中的其他Bean實例作為目標把敞,這種關(guān)系可以由IOC容器的依賴注入提供。Spring默認使用Java動態(tài)代理來創(chuàng)建AOP代理榨惠。Spring目前僅支持將方法調(diào)用作為連接點(Joinpoint)奋早,如果需要把對成員變量的訪問和更新也作為增強處理的連接點,則可以考慮使用AspectJ赠橙。Spring側(cè)重于AOP實現(xiàn)和IOC容器之間的整合耽装,用于幫助解決企業(yè)級開發(fā)中常見問題。Spring AOP采用基于代理的AOP實現(xiàn)方案期揪,而AspectJ則采用編譯時增強的解決方案掉奄。
AOP編程中需要程序員參與的只有三個部分:

  • 第一普通業(yè)務組件。
  • 定義切入點凤薛,一個切入點可以橫切多個業(yè)務組件姓建。
  • 定義增強處理,增強處理就是在AOP框架為普通業(yè)務組織織入的處理動作缤苫。

AOP代理方法=增強處理+目標對象的方法

Spring有如下兩種選擇來定義切入點和增強處理:

  • 基于注解的“零配置”方式:使用@Aspect速兔、@Pointcut等注解來標注切入點和增強處理。
  • 基于XML配置文件的管理方式:使用Spring配置文件來定義切入點和增強處理榨馁。

基于注解的“零配置”方式:

Spring依然采用運行時生成動態(tài)代理的方式來增強目標對象憨栽,所以它不需要增加額外的編譯帜矾,也不需要AspectJ的織入器支持翼虫;而AspectJ采用編譯時增強,所以AspectJ需要自己的編譯器來編譯Java文件屡萤,還需要織入器珍剑。
Spring中啟用對@AspectJ切面配置的支持:

<?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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
        
        <!-- 啟動@AspectJ支持 -->
        <aop:aspectj-autoproxy/>
      
</beans>

以及

<!-- 啟動@AspectJ支持 -->
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>

Spring應用中啟動@AspectJ支持還需要在應用的類加載路徑下添加AspectJ庫:

  • aspectjweaver.jar
  • aspectjrt.jar
    以上兩個jar文件直接在AspectJ安裝目錄的lib中獲取,Spring AOP還需要依賴aopalliance.jar死陆。

1招拙、定義切面:

當啟動了@AspectJ支持后,只要在Spring容器中配置一個帶@AspectJ注解的Bean措译,Spring將會自動識別該Bean别凤,并將該Bean作為切面處理。

//使用@AspectJ定義一個切面類
@Aspect
public class LogAspect{
   //定義該類的其他類容
   .......
}

當使用@AspectJ來修飾一個Java類之后领虹,Spring不會把該Bean當成組件Bea處理规哪,因此負責增強后處理的Bean將會略過該Bean,不會對該Bean進行任何增強處理塌衰。

2诉稍、定義Before增強處理:

在一個切面類里使用@Before來修飾一個方法時蝠嘉,該方法將作為Before增強處理。使用@Before修飾時杯巨,通常需要指定一個value屬性蚤告,該屬性指定一個切入點表達式(既可以是一個已有的切入點,也可以直接定義切入點表達式)服爷,用于指定該增強處理將被織入哪些切入點杜恰。

AuthAspect.java

package entity;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AuthAspect {

    //匹配entity包下所有的類的所有方法作為切入點
    @Before("execution(* entity.*.*(..))")
    public void authority(){
        System.out.println("模擬執(zhí)行權(quán)限檢查!");
    }
}

HelloImpl.java

package entity;



import org.springframework.stereotype.Component;

import inter.Hello;
@Component("hello")
public class HelloImpl implements Hello{

    //定義一個簡單方法仍源,模擬應用中的業(yè)務邏輯方法
    public void foo() {
        System.out.println("執(zhí)行Hello組件的foo()方法");
    }
    //定義一個addUser()方法箫章,模擬應用中添加用戶的方法
    public void addUser(String name,String pass){
        System.out.println("執(zhí)行Hello組件的addUser添加用戶:"+name);
    }

}

beans.xml

<?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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
        <!-- 啟動@AspectJ支持 -->
         <aop:aspectj-autoproxy/>
        <!-- 指定自動搜索Bean文件,自動搜索切面文件 -->
        <context:component-scan base-package="entity">
           <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
        </context:component-scan>
</beans>

AspectjTest.java

package test;





import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import entity.HelloImpl;

public class AspecjTest {
    public static void main(String[] args) {
        ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
        HelloImpl hello=(HelloImpl) ctx.getBean("hello");
        hello.foo();
        hello.addUser("張三", "123456");
    }
    
}

輸出:

模擬執(zhí)行權(quán)限檢查镜会!
執(zhí)行Hello組件的foo()方法
模擬執(zhí)行權(quán)限檢查檬寂!
執(zhí)行Hello組件的addUser添加用戶:張三

使用Before增強處理只能在目標方法執(zhí)行之前織入增強,如果Before增強處理沒有特殊處理戳表,目標方法總會自動執(zhí)行桶至,如果Before處理需要阻止目標方法的執(zhí)行,可通過拋出一個異常來實現(xiàn)匾旭。Before增強處理時镣屹,目標方法還未獲得執(zhí)行的機會,所以Before增強處理無法訪問目標方法的返回值价涝。

3女蜈、定義AfterReturning增強處理:

AfterReturning增強處理將在目標方法正常完成后被織入。
@AfterReturning注解可指定如下兩個常用屬性:

  • pointcut/value:它們都用于指定該切入點對應的切入點表達式色瘩。一樣即可是一個已有的切入點伪窖,也可以直接定義切入點表達式。當指定了pointcut屬性值后居兆,value屬性將被覆蓋覆山。
  • returning:該屬性指定一個形參名,用于表示Advice方法中可定義與此同名的形參泥栖,該形參可用于訪問目標方法的返回值簇宽。除此之外,在Advice方法中定義該形參(代表目標方法的返回值)時指定的類型吧享,會限制目標方法必須返回指定類型的值或沒有返回值魏割。
//定義一個切面
@Aspect
public class LogAspect{
  //匹配entity包下所有類的所有方法的執(zhí)行作為切入點
  @AfterReturning(returning="rvt",pointcut="execution(* entity.*.*())")
  //聲明rvt時指定的類型會限制目標方法必須返回指定類型的值或沒有返回值
  //此處將rvt的類型聲明為Object,意味著對目標方法的返回值不加限制
  public void log(Object rvt){
       System.out.println("獲得目標方法返回值"+rvt);
       System.out.println("模擬記錄日志功能....");
   }
}

@AfterReturning注解的returning屬性所指定的形參名對應于增強處理中的一個形參名钢颂,當目標方法執(zhí)行返回后钞它,返回值作為相應的參數(shù)值傳入增強處理方法。使用returning屬性還有 一個額外的作用:它可用于限定切入點只匹配具有對應返回值類型的方法。

4须揣、定義AfterThrowing增強處理:

AfterThrowing增強處理主要用于處理程序中未處理的異常盐股。
使用@AfterThrowing注解時可指定如下兩個常用屬性:

  • pointcut/value:都用于指定該切入點對應的切入表達式。
  • throwing:該屬性值指定一個形參名耻卡,用于表示Advice方法中可定義與此同名的形參疯汁,該形參用于訪問目標方法拋出的異常。在Advice方法中定義該形參(代表目標方法拋出的異常)時指定的類型卵酪,會限制目標方法必須拋出指定類型的異常幌蚊。
//定義一個切面
@Aspect
public class RepairAspect{
  //匹配entity包下所有類的所有方法的執(zhí)行作為切入點
  @AfterThrowing(throwing="ex",pointcut="execution(* entity.*.*())")
  //聲明ex時指定的類型會限制目標方法必須拋出指定的類型的異常
  //此處將ex的類型聲明為Throwable,意味著對目標方法拋出的異常不加限制
  public void doRecoveryActions(Throwable ex){
       System.out.println("目標方法中拋出的異常"+ex);
       System.out.println("模擬Advice對異常的修復....");
   }
}

使用throwing屬性還用一個額外的作用:它可用于限定切入點只匹配指定類型的異常溃卡。

5溢豆、After增強處理:

  • AfterReturning增強處理只有在目標方法成功完成后才會被織入。
  • After增強處理不管目標方法如何結(jié)束(包括成功完成和遇到異常終止兩種情況)瘸羡,他都會被織入漩仙。

After增強處理必須準備處理正常返回或異常返回兩種情況,這種處理通常用于釋放資源犹赖。使用@After注解修飾一個方法队他,即可將該方法轉(zhuǎn)成After增強處理。使用@After注解時需要指定一個value屬性峻村,該屬性值用于指定該增強處理被織入的切入點麸折。

//定義一個切面
@Aspect
public class ReleaseAspect{
    //匹配entity包下所有的類的所有方法的執(zhí)行作為切入點
    @After("execution(* entity.*.*())")
    public void release(){
        System.out.println("模擬方法結(jié)束后的釋放資源...");
    }
}

After增強處理的作用非常類似于異常處理中的finally塊的作用。

6粘昨、Around增強處理:

@Around注解用于修飾Around增強處理垢啼,Around增強處理是功能較強大得增強處理,它近似等于Before和AfterReturning增強處理的總和张肾,Around增強處理即可在執(zhí)行目標方法之前織入增強動作芭析,也可以在執(zhí)行目標方法之后織入增強處理。
Around增強處理可以決定目標方法在什么時候執(zhí)行捌浩,如何執(zhí)行放刨,甚至可以完全阻止目標方法的執(zhí)行。Around增強處理的功能雖然強大尸饺,但通常需要在線程安全的環(huán)境下使用。如果需要目標方法執(zhí)行之前和執(zhí)行之后共享某種狀態(tài)數(shù)據(jù)助币,則該考慮使用Around增強處理浪听;尤其是需要改變目標方法的返回值時,則只能使用Around增強處理眉菱。
當定義一個Around增強處理方法時迹栓,該方法的第一個形參必須是ProceedingJoinPoint類型(至少包含一個形參),在增強處理方法體內(nèi)俭缓,調(diào)用ProceedingJoinPoint參數(shù)的proceed()方法才會執(zhí)行目標方法---這就是Around增強處理可以完全控制目標方法的執(zhí)行時機克伊、如何執(zhí)行的關(guān)鍵酥郭;如果程序沒有調(diào)用proceedingJoinPoint參數(shù)的proceed()方法,則目標方法不會被執(zhí)行愿吹。
使用Around增強處理可以取得目標方法最大的控制權(quán)不从,既可以完全控制目標方法的執(zhí)行,一刻改變執(zhí)行目標方法的參數(shù)犁跪,還可改變目標方法的返回值椿息。

7、訪問目標方法的參數(shù):

訪問目標方法最簡單的做法是定義增強處理方法時將第一個參數(shù)定義為JoinPoint類型坷衍,當該增強處理方法被調(diào)用時寝优,該JoinPoint參數(shù)就代表了織入增強的連接點。JoinPoint里包含如下幾個常用的方法:

  • Object[] getArgs():返回執(zhí)行目標方法時的參數(shù)枫耳。
  • Signature getSignature():返回被增強的方法的相關(guān)信息乏矾。
  • Object getTarget():返回被增強處理的目標對象。
  • Object getThis():返回AOP框架為目標對象生成的代理對象迁杨。

當使用Around增強處理是妻熊,需要將第一個參數(shù)定義為ProceedingJoionPoint類型,該類型是JoinPoint類型的子類仑最。

Spring AOP 采用和AspectJ一樣的優(yōu)先順序來織入增強處理:在“進入連接點時扔役,具有最高優(yōu)先級的增強處理將先被織入。在“退出”連接點時警医,具有最高優(yōu)先級的增強處理會最后被織入亿胸。
當不同切面的兩個增強處理需要在同一個連接點被織入時,Spring AOP將以隨機的順序來織入這兩個增強處理预皇。如果應用需要指定不同切面類里增強處理的優(yōu)先級侈玄,Spring提供了如下兩種解決方案:

  • 讓切面實現(xiàn)org.springframework.core.Ordered接口,實現(xiàn)該接口只需要實現(xiàn)一個int getOrder()方法吟温,該方法的返回值越小序仙,優(yōu)先級越高。
  • 直接使用@Order注解來修飾一個切面類鲁豪,使用@Order注解時可指定一個int型的value屬性潘悼,該值越小,則優(yōu)先級越高爬橡。

8治唤、定義切入點:

定義切入點,其實質(zhì)就是為一個切入點表達式起一個名稱糙申,從而允許在多個增強處理中重用該名稱宾添。Spring AOP只支持將Spring Bean的方法執(zhí)行作為連接點,所以可以吧切入點看成所有能和切入點表達式匹配的Bean方法,切入點定義包含兩個部分:

  • 一個切入點表達式缕陕。
  • 一個包含名字和任意參數(shù)的方法名粱锐。
    其中切入點表達式用于指定該切入點和哪些方法進行匹配,包含名字和任意參數(shù)的方法簽名將作為該切入點的名稱扛邑。
//使用@Pointcut注解定義切入點
@Pointcut("execution(* transfer(..))")
//使用一個返回值為void怜浅、方法體為空的方法來命名切入點
private void anyOldTransfer(){...}

如果需要使用本切面中的切入點,則可在使用@Before鹿榜、@After海雪、@Around等注解來定義Advice時,使用pointcut或value屬性值引入已有的切入點舱殿。

@AfterReturning(pointcut="myPointcut()",returning="retVal")
public void writeLog(String msg,Object retVal){...}

使用其他切面類中的切入點時奥裸,應該使用切面類作為前綴來限制切入點。

9沪袭、切入點指示符:

  • execution:用于匹配執(zhí)行方法的連接點湾宙,這是Spring AOP中最主要的切入點指示符。
  • within:用于限定匹配特定類型的連接點冈绊,當使用Spring AOP的時候侠鳄,只能匹配方法執(zhí)行的連接點。
//在entity包中的任意連接點(在Spring AOP中只是方法執(zhí)行的連接點)
within(entity.*)
//在entity包或子包中的任意連接點(在Spring AOP中只是方法執(zhí)行的連接點)
within(entity..*)
  • this:用于限定AOP代理必須必須是指定類型的實例死宣,匹配該對象的所有連接點伟恶。當使用Spring AOP的時候,只能匹配方法執(zhí)行的連接點毅该。
  • target:用于限定目標對象必須是指定類型的實例博秫,匹配該對象的所有連接點。當使用Spring AOP的時候眶掌,只能匹配方法執(zhí)行的連接點挡育。
  • args:用于對連接點的參數(shù)類型進行限制,要求參數(shù)類型是指定類型的實例朴爬。當使用Spring AOP的時候即寒,只能匹配方法執(zhí)行的連接點。
  • bean:用于限定只匹配指定Bean實例內(nèi)的連接點召噩,實際上只能使用方法執(zhí)行作為連接點母赵。定義表達式時需要傳入Bean的id或name屬性,表示值匹配該Bean實例內(nèi)的連接點蚣常。支持使用“*”通配符市咽。
//匹配tradeService Bean實例內(nèi)方法執(zhí)行的連接點
bean(tradeService)
//匹配名字以Service結(jié)尾的Bean實例內(nèi)方法執(zhí)行的連接點
bean(*Service)

10、組合切入點表達式:

  • &&:要求連接點同時匹配兩個切入點表達式抵蚊。
  • ||:只要求連接點匹配任意一個切入點表達式。
  • !:要求切入點不匹配指定的切入點表達式贞绳。

基于XML配置文件的管理方式:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谷醉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子冈闭,更是在濱河造成了極大的恐慌俱尼,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萎攒,死亡現(xiàn)場離奇詭異遇八,居然都是意外死亡,警方通過查閱死者的電腦和手機耍休,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門刃永,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人羊精,你說我怎么就攤上這事斯够。” “怎么了喧锦?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵读规,是天一觀的道長。 經(jīng)常有香客問我燃少,道長束亏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任阵具,我火速辦了婚禮碍遍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怔昨。我一直安慰自己雀久,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布趁舀。 她就那樣靜靜地躺著赖捌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矮烹。 梳的紋絲不亂的頭發(fā)上越庇,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音奉狈,去河邊找鬼卤唉。 笑死,一個胖子當著我的面吹牛仁期,可吹牛的內(nèi)容都是我干的桑驱。 我是一名探鬼主播竭恬,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼熬的!你這毒婦竟也來了痊硕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤押框,失蹤者是張志新(化名)和其女友劉穎岔绸,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體橡伞,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡盒揉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了兑徘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刚盈。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖道媚,靈堂內(nèi)的尸體忽然破棺而出扁掸,到底是詐尸還是另有隱情,我是刑警寧澤最域,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布谴分,位于F島的核電站,受9級特大地震影響镀脂,放射性物質(zhì)發(fā)生泄漏牺蹄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一薄翅、第九天 我趴在偏房一處隱蔽的房頂上張望沙兰。 院中可真熱鬧,春花似錦翘魄、人聲如沸鼎天。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斋射。三九已至,卻和暖如春但荤,著一層夾襖步出監(jiān)牢的瞬間罗岖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工腹躁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留桑包,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓纺非,卻偏偏與公主長得像哑了,于是被迫代替她去往敵國和親赘方。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器停做,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 當相同的切面里的兩個增強處理需要在相同的連接點被織入時资溃,Spring AOP將以隨機的方式來織入這兩個增強處理,沒...
    FTOLsXD閱讀 1,255評論 0 1
  • **** AOP 面向切面編程 底層原理 代理1钣啤0裾啤! 今天AOP課程1乘综、 Spring 傳統(tǒng) AOP2憎账、 Spri...
    luweicheng24閱讀 1,355評論 0 1
  • 本章內(nèi)容: 面向切面編程的基本原理 通過POJO創(chuàng)建切面 使用@AspectJ注解 為AspectJ切面注入依賴 ...
    謝隨安閱讀 3,127評論 0 9
  • 因為工作需求,自己去了解一下aop并做下的記錄卡辰,當然大部分都是參考他人博客以及官方文檔胞皱。 目錄 [關(guān)于 AOP](...
    forip閱讀 2,267評論 1 20