程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> [Spring實戰系列](18)注解切面

[Spring實戰系列](18)注解切面

編輯:JAVA綜合教程

[Spring實戰系列](18)注解切面


使用注解來創建切面是AspectJ 5所引入的關鍵特性。在AspectJ 5之前,編寫AspectJ切面需要學習一種Java語言的擴展,但是AspectJ面向注解的模型可以非常簡單的通過少量注解把任意類轉變為切面。   回顧一下Audience類,沒有任何地方讓它成為一個切面,我們不得不使用XML聲明通知和切點。   我們通過@AspectJ注解,我們再看看Audience類,不需要任何額外的類或Bean聲明就能將它轉換為一個切面。  
package com.sjf.bean;
/** * 歌手實體類 * @author sjf0115 * */public class Singer { public void perform() { System.out.println("正在上演個人演唱會... "); }}  
package com.sjf.bean;
import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;/** * 觀眾實體類(注解為切面) * @author sjf0115 * */@Aspectpublic class Audience { // 定義切點 @Pointcut("execution(* com.sjf.bean.Singer.perform(..))") public void SingerPerform(){ // 空方法 } // 表演之前 @Before("SingerPerform()") public void takeSeats(){ System.out.println("the audience is taking their seats..."); } // 表演成功之後 @AfterReturning("SingerPerform()") public void applaud(){ System.out.println("very good, clap clap clap..."); } // 表演失敗之後 @AfterThrowing("SingerPerform()") public void demandRefund(){ System.out.println("very bad, We want our money back..."); }} 新的Audience類現在已經使用@AspectJ注解進行標注。該注解標示了Audience不僅僅是一個POJO,還是一個切面。   @Pointcut注解用於定義一個可以在@AspectJ切面內可重用的切點。@Pointcut注解的值是一個AspectJ切點表達式(這裡標示切點必須匹配Singer的perform()方法)。切點的名稱來源於注解所應用的方法名稱。因為,該切點的名稱為SingerPerform()。SingerPerform()方法的實際內容並不重要,它只是一個標示,供@Pointcut注解依附。   Audience的每一個方法都是用通知注解來標注。takeSeats()方法使用@Before注解來標示它們是前置通知方法。applaud()方法使用@AfterReturning注解來標示它是後置通知方法。demandRefund()方法使用@AfterThrowing注解標示它在拋出異常時該方法被會調用。SingerPerform()切點的名稱作為參數的值賦予給所有的通知注解,來標示每一個通知方法應該應用在哪。   注意:
除了注解和無操作的SingerPerform()方法,Audience類在實現上並沒有任何改變,Audience類仍然是一個簡單的Java對象,能夠像以前一樣使用(在Spring中使用Bean進行配置)。   因為Audience類本身包含了所有它所需要定義的切點和通知,所以我們不在需要在XML配置中聲明切點和通知。為了讓Spring將Audience應用為一個切面,我們需要在Spring上下文中聲明一個自動代理Bean,該Bean知道如何把@AspectJ注解所標注的Bean轉變為代理通知。   為此,Spring自帶了名為AnnotationAwareAspectJProxyCreator的自動代理創建類。我們可以在Spring上下文中把AnnotationAwareAspectJProxyCreator注冊為一個Bean,但是這個類文字太長,不宜使用。因此,我們使用Spring的aop空間提供的一個自定義配置元素()來代替前者,這個更易使用。
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd 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"> 配置元素將在Spring上下文中創建一個AnnotationAwareAspectJProxyCreator類,它會自動代理一些Bean,這些Bean的方法需要與使用@AspectJ注解的Bean中所定義的切點相匹配。   運行結果:
theaudienceistakingtheirseats... 正在上演個人演唱會... verygood,clapclapclap...   注意:
元素和@AspectJ注解都是把一個POJO轉變為一個切面的有效方式。但是相對@AspectJ的一個明顯優勢是:不需要實現切面功能的代碼(本例中是Audience類代碼)。通過@AspectJ,我們必須標注類和方法,它需要有源碼   1. 注解環繞通知   像Spring基於XML的AOP一樣,@AspectJ注解的使用不僅僅限於定義前置和後置通知類型。我們還可以創建環繞通知。
@Around("SingerPerform()")
public void PerformTime(ProceedingJoinPoint joinPoint){ // 演出之前 System.out.println("the audience is taking their seats..."); try { long start = System.currentTimeMillis(); // 執行演出操作 joinPoint.proceed(); long end = System.currentTimeMillis(); // 演出成功 System.out.println("very good, clap clap clap..."); System.out.println("該演出共需要 "+(end - start) + " milliseconds"); } catch (Throwable e) { // 演出失敗 System.out.println("very bad, We want our money back..."); e.printStackTrace(); } } 在這裡,@Around注解標示了PerformTime()方法將被作為環繞通知應用與SingerPerform()切點。和之前使用XML方式唯一的區別就是用@Around注解所標注的。簡單的使用@Around注解來標注方法並不足以調用proceed()方法,因此,被環繞通知的方法必須接受一個ProceedingJoinPoint對象作為方法入參,並在對象上調用proceed()方法。   2. 傳遞參數給所標注的通知   之前我們曾經使用Spring基於XML的切面聲明為通知傳遞參數,而是@AspectJ注解為通知傳遞參數,與之相比並沒有太大的區別。
package com.sjf.bean;
/** * 歌手實體類 * @author sjf0115 * */public class Singer { public void perform(String song) { System.out.println("正在上演個人演唱會... " + song); }}  
package com.sjf.bean;
import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;/** * 主辦方實體類 * @author sjf0115 * */@Aspectpublic class Organizers { // 定義切點 @Pointcut("execution(* com.sjf.bean.Singer.perform(String)) and args(song)") public void SingerPerform(){ // } // 表演之前 @Before("SingerPerform() and args(song)") public void BeforeSong(String song){ System.out.println("演唱會馬上就開始了,演唱歌曲為 " + song); }} 元素變為@Pointcut注解,元素變為@Before注解。     不知道下面配置出現報錯如何解決?求解.....
	// 定義切點
@Pointcut("execution(* com.sjf.bean.Singer.perform(String)) and args(song)") public void SingerPerform(String song){ // } // 表演之前 @Before("SingerPerform(song)") public void BeforeSong(String song){ System.out.println("演唱會馬上就開始了,演唱歌曲為 " + song); }   來源於:《Spring實戰》  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved