javascript
Spring AOP 切点(pointcut)表达式
概括
這遍文章將介紹Spring AOP切點表達(dá)式(下稱表達(dá)式)語言,首先介紹兩個面向切面編程中使用到的術(shù)語。
-
連接點(Joint Point):廣義上來講,方法、異常處理塊、字段這些程序調(diào)用過程中可以抽像成一個執(zhí)行步驟(或者說執(zhí)行點)的單元。從Spring AOP來講,就是指java的方法和異常處理代碼塊。
- 切點(Pointcut):是連接點的描述定義,Spring AOP通過切點來定位到哪些連接點。切點表達(dá)式語言就是切點用來定義連接點的語法。
用例
表達(dá)式會出現(xiàn)在以下幾種場景
在上面的代碼片段中的注解@Pointcut的參數(shù)"within(@org.springframework.stereotype.Reposity *)"就是使用的切點表達(dá)式。而上代碼中的repositoryClassMethods()方法被AOP AspectJ定義為切點簽名方法,作用是使得通知的注解可以通過這個切點簽名方法連接到切點,通過解釋切點表達(dá)式找到需要被切入的連接點。最終的目的都是為了找到需要被切入的連接點。像下面這段代碼片段
如果你的項目是基于xml配置的,可以在<aop:pointcut>標(biāo)簽里配置表達(dá)式來定位連接點,參考以下代碼片段:
<aop:config><aop:pointcut id="anyDaoMethod"expression="@target(org.springframework.stereotype.Repository)"/> </aop:config>切點指示符
切點指示符是切點定義的關(guān)鍵字,切點表達(dá)式以切點指示符開始。開發(fā)人員使切點指示符來告訴切點將要匹配什么,有以下9種切點指示符:execution、within、this、target、args、@target、@args、@within、@annotation,下面一一介結(jié)這9種切點指示符。
execution
execution是一種使用頻率比較高比較主要的一種切點指示符,用來匹配方法簽名,方法簽名使用全限定名,包括訪問修飾符(public/private/protected)、返回類型,包名、類名、方法名、參數(shù),其中返回類型,包名,類名,方法,參數(shù)是必須的,如下面代碼片段所示:
@Pointcut("execution(public String org.baeldung.dao.FooDao.findById(Long))")上面的代碼片段里的表達(dá)式精確地匹配到FooDao類里的findById(Long)方法,但是這看起來不是很靈活。假設(shè)我們要匹配FooDao類的所有方法,這些方法可能會有不同的方法名,不同的返回值,不同的參數(shù)列表,為了達(dá)到這種效果,我們可以使用通配符。如下代碼片段所示:
@Pointcut("execution(* org.baeldung.dao.FooDao.*(..))")第一個通配符匹配所有返回值類型,第二個匹配這個類里的所有方法,()括號表示參數(shù)列表,括號里的用兩個點號表示匹配任意個參數(shù),包括0個
within
使用within切點批示符可以達(dá)到上面例子一樣的效果,within用來限定連接點屬于某個確定類型的類。如下面代碼的效果與上面的例子是一樣的:
@Pointcut("within(org.baeldung.dao.FooDao)")我們也可以使用within指示符來匹配某個包下面所有類的方法(包括子包下面的所有類方法),如下代碼所示:
@Pointcut("within(org.baeldung..*)")this 和 target
this用來匹配的連接點所屬的對象引用是某個特定類型的實例,target用來匹配的連接點所屬目標(biāo)對象必須是指定類型的實例;那么這兩個有什么區(qū)別呢?原來AspectJ在實現(xiàn)代理時有兩種方式:
1、如果當(dāng)前對象引用的類型沒有實現(xiàn)自接口時,spring aop使用生成一個基于CGLIB的代理類實現(xiàn)切面編程
2、如果當(dāng)前對象引用實現(xiàn)了某個接口時,Spring aop使用JDK的動態(tài)代理機制來實現(xiàn)切面編程
this指示符就是用來匹配基于CGLIB的代理類,通俗的來講就是,如果當(dāng)前要代理的類對象沒有實現(xiàn)某個接口的話,則使用this;target指示符用于基于JDK動態(tài)代理的代理類,通俗的來講就是如果當(dāng)前要代理的目標(biāo)對象有實現(xiàn)了某個接口的話,則使用target.:
比如在上面這段代碼示例中,spring aop將使用jdk的動態(tài)代理來實現(xiàn)切面編程,在編寫匹配這類型的目標(biāo)對象的連接點表達(dá)式時要使用target指示符, 如下所示:
@Pointcut("target(org.baeldung.dao.BarDao)")如果FooDao類沒有實現(xiàn)任何接口,或者在spring aop配置屬性:proxyTargetClass設(shè)為true時,Spring Aop會使用基于CGLIB的動態(tài)字節(jié)碼技為目標(biāo)對象生成一個子類將為代理類,這時應(yīng)該使用this指示器:
@Pointcut("this(org.baeldung.dao.FooDao)")參數(shù)
參數(shù)指示符是一對括號所括的內(nèi)容,用來匹配指定方法參數(shù):
@Pointcut("execution(* *..find*(Long))")這個切點匹配所有以find開頭的方法,并且只一個Long類的參數(shù)。如果我們想要匹配一個有任意個參數(shù),但是第一個參數(shù)必須是Long類的,我們這可使用下面這個切點表達(dá)式:
@Pointcut("execution(* *..find*(Long,..))")@Target
這個指示器匹配指定連接點,這個連接點所屬的目標(biāo)對象的類有一個指定的注解:
@Pointcut("@target(org.springframework.stereotype.Repository)")@args
這個指示符是用來匹配連接點的參數(shù)的,@args指出連接點在運行時傳過來的參數(shù)的類必須要有指定的注解,假設(shè)我們希望切入所有在運行時接受實@Entity注解的bean對象的方法:
@Pointcut("@args(org.baeldung.aop.annotations.Entity)") public void methodsAcceptingEntities() {}為了在切面里接收并使用這個被@Entity的對象,我們需要提供一個參數(shù)給切面通知:JointPoint:
@Before("methodsAcceptingEntities()") public void logMethodAcceptionEntityAnnotatedBean(JoinPoint jp) {logger.info("Accepting beans with @Entity annotation: " + jp.getArgs()[0]); }@within
這個指示器,指定匹配必須包括某個注解的的類里的所有連接點:
@Pointcut("@within(org.springframework.stereotype.Repository)")上面的切點跟以下這個切點是等效的:
@Pointcut("within(@org.springframework.stereotype.Repository *)")@annotation
這個指示器匹配那些有指定注解的連接點,比如,我們可以新建一個這樣的注解@Loggable:
@Pointcut("@annotation(org.baeldung.aop.annotations.Loggable)") public void loggableMethods() {}我們可以使用@Loggable注解標(biāo)記哪些方法執(zhí)行需要輸出日志:
@Before("loggableMethods()") public void logMethod(JoinPoint jp) {String methodName = jp.getSignature().getName();logger.info("Executing method: " + methodName); }切點表達(dá)式組合
可以使用&&、||、!、三種運算符來組合切點表達(dá)式,表示與或非的關(guān)系。
@Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {}@Pointcut("execution(* *..create*(Long,..))") public void firstLongParamMethods() {}@Pointcut("repositoryMethods() && firstLongParamMethods()") public void entityCreationMethods() {}作者的github例子:https://github.com/eugenp/tutorials/tree/master/spring-mvc-java
from:http://blog.51cto.com/5914679/2092253?
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的Spring AOP 切点(pointcut)表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RabbitMQ系统3.5.3版本中文完
- 下一篇: Spring AOP切点表达式详解