<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Spring容器包含兩個重要的特性:面向切面程式設計(AOP)和控制反轉(IOC)。面向切面程式設計是物件導向(OOP)的一種補充,在物件導向程式設計的過程中程式設計針對的目標是一個個物件,而面向切面程式設計中程式設計針對的目標是一個個切面。切面支援跨型別跨物件(如事務的切面可以加在任何地方)進行模組化。
AOP是Spring的關鍵特性之一,雖然Spring的IOC特性並不依賴於AOP(意味著你可以只使用Spring的IOC特性而不使用AOP特性),但是二者結合起來可以靈活的實現很多中介軟體解決方案。比如我們經常使用的事務(@Transaction),就是通過AOP方案實現的。本文重點介紹AOP程式設計中的一些術語,這些術語不僅僅侷限於Spring,它適用於所有的AOP程式設計。
Spring的AOP使用純Java語言實現(如AspectJ就不是Java語言),不需要任何額外的編譯流程,不需要修改類載入器,適用於任何Servlet容器和應用服務。Spring的AOP只支援方法攔截,不支援欄位攔截,如果使用者需要使用欄位攔截,可以考慮引入AspectJ等類似的框架。
Spring的AOP框架和其它的框架有些不同,Spring的Aop框架不僅僅是為了提供一個AOP功能,它更重要的功能是和Spring的IOC容器結合,提供一些企業應用服務的解決方案(如事務等),我們可以和定義一個普通Bean一樣的方式去定以一個切面。Spring的AOP不支援非常細粒度的AOP,只支援對容器中的Bean進行AOP,如果需要更細粒度的AOP,可以考慮使用AspectJ。Spring容器的一個優秀的特性就是非侵入性,所以你可以靈活的選擇自己的AOP方案,不一定非要使用Spring的方案。
Spring對實現介面的方法預設使用Java動態代理實現AOP攔截,對於非介面方法則會使用CGLIB位元組碼工具實現代理。
@AspectJ註解可以把一個普通的Java類宣告為切面。@AspectJ註解是AspectJ5引入的註解,Spring雖然可以讀取AspectJ5的註解用於切面後設資料的設定,但是在執行的時候使用的仍然是Spring AOP進行代理,而沒有使用AspectJ的編譯器或者織入邏輯。我們會在後續討論如何在Spring中使用AspectJ的編譯器和織入邏輯。
Spring預設沒有啟用AspectJ,如果你需要Spring支援@AspectJ註解對應的切面,可以通過在設定類上新增註解或者使用XML啟用設定(AspectJ所在的包是:aspectjweaver.jar)。
@Configuration @EnableAspectJAutoProxy public class AppConfig { }
<aop:aspectj-autoproxy/>
當啟用AspectJ支援之後,開發者定義的任何Aspect切面會自動地被檢測到,然後Spring AOP會對切面進行攔截。下面兩個例子展示瞭如何設定AspectJ切面,你可以通過新增@Component註解把切面Bean註冊到Spring容器中。
<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect"> <!-- configure properties of the aspect here --> </bean>
package org.xyz; import org.aspectj.lang.annotation.Aspect; @Aspect public class NotVeryUsefulAspect { }
切入點程式執行過程中我們感興趣的一個點,Spring的AOP框架只支援發現對Spring Bean方法上的切入點,因此你可以簡單的把切入點理解為SpringBean的方法。
切入點確定感興趣的連線點,從而使我們能夠控制何時執行通知。springaop只支援springbean的方法執行連線點,因此可以將切入點看作與springbean上方法的執行相匹配。切入點宣告由兩部分組成:一部分是由名稱和任何引陣列成的簽名,另一部分是確定我們感興趣的方法執行的切入點表示式。在AOP的@AspectJ註釋樣式中,切入點簽名由常規方法定義提供,切入點表示式由@pointcut註釋指示(用作切入點簽名的方法必須具有void返回型別)。切入點由兩部分組成,一部分是用於區別不同切入點的標識(下面例子中的 private void anyOldTransfer() {}
)),另外一部分是確定我們感興趣的Bean方法的表示式(下面例子中的 @Pointcut("execution(* transfer(..))")
), 下面的例子展示了一個切入點的定義:
@Pointcut("execution(* transfer(..))") // the pointcut expression private void anyOldTransfer() {} // the pointcut signature
Spring匹配切入點的語法使用了AspectJ5中的表示式語法,我們可以參考AspectJ檔案相關的語法.
Spring支援下面常見的AspectJ切面定義語法:
@Pointcut("execution(public * *(..))") private void anyPublicOperation() {}
@Pointcut("within(com.xyz.myapp.trading..*)") private void inTrading() {}
@target(org.springframework.transaction.annotation.Transactional)
// 當前AOP物件實現了 IPointcutService介面的任何方法 @Pointcut("target(cn.javass.spring.chapter6.service.IPointcutService)") private void anyPublicOperation() {}
args(java.io.Serializable)
@target(org.springframework.transaction.annotation.Transactional)
@args(com.xyz.security.Classified)
@within(org.springframework.transaction.annotation.Transactional)
@annotation(org.springframework.transaction.annotation.Transactional)
我們可以通過“&&”和“||”對多個條件進行組合,AspectJ還有很多其它的表示式,但是Spring不支援除上述表示式以外的其它表示式。AspectJ其它表示式包含: call, get, set, preinitialization, staticinitialization, initialization, handler, adviceexecution, withincode, cflow, cflowbelow, if, @this, @withincode等。
我們在使用Spring的代理方法之前,應該知道其代理原理。Java動態代理只能攔截public介面方法上的呼叫,CGLib只能攔截public、protected和defult方法。如果你需要更深層次的攔截,可以考慮使用底層的Aspectj。
我們在上面的步驟定義好了一個切入點,我們現在就可以對這個切入點進行額外操作,這些額外操作被稱為增強,Spring支援四種增強方式:前增強、後增強、異常增強和環繞增強。Spring支援在增強方法的定義上直接定義切入點。
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class BeforeExample { @Before("com.xyz.myapp.CommonPointcuts.dataAccessOperation()") public void doAccessCheck() { // ... } }
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class BeforeExample { @Before("execution(* com.xyz.myapp.dao.*.*(..))") public void doAccessCheck() { // ... } }
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.AfterReturning; @Aspect public class AfterReturningExample { @AfterReturning( pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()", returning="retVal") public void doAccessCheck(Object retVal) { // ... } }
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.AfterThrowing; @Aspect public class AfterThrowingExample { @AfterThrowing( pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()", throwing="ex") public void doRecoveryActions(DataAccessException ex) { // ... } }
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.ProceedingJoinPoint; @Aspect public class AroundExample { @Around("com.xyz.myapp.CommonPointcuts.businessService()") public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { // start stopwatch Object retVal = pjp.proceed(); // stop stopwatch return retVal; } }
我們前面說過,Spring AOP通過動態代理和CGLIB實現AOP物件的代理。我們可以通過如下設定設定動態代理全部走CGLIB。
<aop:config proxy-target-class="true"> <!-- other beans defined here... --> </aop:config>
Spring AOP實現代理的核心類是 AspectJProxyFactory
,我們可以使用這個類程式設計式生成代理物件:
// create a factory that can generate a proxy for the given target object AspectJProxyFactory factory = new AspectJProxyFactory(targetObject); // add an aspect, the class must be an @AspectJ aspect // you can call this as many times as you need with different aspects factory.addAspect(SecurityManager.class); // you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspect factory.addAspect(usageTracker); // now get the proxy object... MyInterfaceType proxy = factory.getProxy()
到此這篇關於Spring基礎之AOP的概念介紹的文章就介紹到這了,更多相關spring aop概念內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45