1. 程式人生 > >六、面向切面的spring(2)

六、面向切面的spring(2)

class 播放 iso 類型 tro interface proc 透明 功能

這個是承接五的,這部分主要的內容是在XML中聲明切面。

一、在XML中聲明切面

讓我們先看一下spring中的AOP配置元素有哪些:

AOP配置元素 用途
<aop:advisor> 定義AOP通知器
<aop:after> 定義AOP後置通知(不管被通知的方法是否成功)
<aop:after-returning> 定義AOP返回通知
<aop:around> 定義AOP環繞通知
<aop:aspect> 定義一個切面
<aop:aspectj-autoproxy> 啟用@AspectJ註解驅動切面
<aop:before> 定義一個
<aop:config> 頂層的AOP配置元素,大多數的
<aop:declare-parents> 以透明的方式為被通知的對象引入額外的接口
<aop:pointcut> 定義一個切點

 1 //聲明的Audience類
 2 package concert;
 3 public class Audience {
 4   public void silenceCellPhones(){
 5     System.out.println("Silence cell phones");
6 } 7 8 public void takeSeats(){ 9 System.out.println("Taking seats"); 10 } 11 12 public void applause(){ 13 System.out.println("CLAP CLAP CLAP!!!"); 14 } 15 16 public void demadRefund(){ 17 System.out.println("Demanding a refund"); 18 } 19 }

1、聲明前置和後置通知

通過XML方式將無註解的Audience聲明為切面

 1  <aop:config>
 2     //引用audience bean
 3     <aop:aspect ref="audience">
 4       <aop:before 
 5        pointcut="execution(** concert.Performance.perform(..))"
 6        method="silenceCellPhone" />
 7   
 8       <aop:before 
 9        pointcut="execution(** concert.Performance.perform(..))"
10        method="takeSeats" />
11  
12       <aop:after-returning
13        pointcut="execution(** concert.Performance.perform(..))"
14        method="applause" />
15  
16        <aop:after-throwing
17        pointcut="execution(** concert.Performance.perform(..))"
18        method="demandRefund" />
19    </aop:aspect>
20 </aop:config>
21 
22 //使用<aop:pointcut> 定義命名切點
23  <aop:config>
24     //引用audience bean
25     <aop:aspect ref="audience">
26       <aop:point 
27         id="performance"
28         expression="execution(** concert.Performance.perform(..))"
29       />
30       <aop:before 
31         pointcut="performance"
32         method="silenceCellPhone" />
33   
34       <aop:before 
35         pointcut="performance"
36        method="takeSeats" />
37  
38       <aop:after-returning
39        pointcut="performance"
40        method="applause" />
41  
42        <aop:after-throwing
43       pointcut="performance"
44        method="demandRefund" />
45    </aop:aspect>
46 </aop:config>

2、聲明環繞通知

 1 package concert;
 2 import org.aspectj.lang.PreceedingJoinPoint;
 3 
 4 public class Audience{
 5   public void watchPerformance(PreceedingJoinPoint jp){
 6     try{
 7       System.out.println("Sliencing cell phones");
 8       System.out.println("Taking seats");
 9       jp.proceed();
10       System.out.println("CLAP CLAP CLAP!!!");
11     }catch(Throwable e){
12       System.out.println("Demanding a refund");
13     }
14   }
15 }
16 
17 //xml中配置環繞通知
18 <aop:config>
19   <aop:aspect ref="audience">
20     <aop:pointcut id="performance" experssion="execution(** concert.Performance.perform(..))" />
21     <aop:around pointcut-ref="performance" method="watchPerformance" />
22   </aop:aspect>
23 </aop:config>

3、為通知傳遞參數

//使用參數化的通知來記錄磁道播放的次數
package soundsystem;
import java.util.HashMap;
import java.util.Map;

public class TrackCounter {
  private Map<Integer,Integer> trackCounts = new HashMap<Integer,Integer>();
  
  public void trackPlayed(int trackNumber) {}
  
  public void countTrack(int trackNumber){
    int currentCount = getPlayCount(trackNumber);
    trackCounts.put(trackNumber, currentCount +1);
  }
  
  public int getPlayCount(int trackNumber){
    return trackCounts.countainsKey(trackNumber) ? trackCounts.get(trackNumber) : 0;
  }
}

//在XML 中將TrackCounter配置為參數化的切面
<bean id="trackCounter" class="soundsystem.TrackCounter " />
<bean id="cd" class="soundsystem.BlackDisc" >
  <property name="title" value="此時此刻" />
  <property name="artist" value="許巍" />
  <property name="tracks" >
    <list>
      <value>空谷幽蘭</value>
      <value>愛情</value>
      <value>此時此刻</value>
      <value>靈巖</value>
      <value>救贖之旅</value>
      <value>心願</value>
      <value>逍遙行</value>
      <value>喜悅</value>
      <value>世外桃源</value>
      <value>出離</value>
    </list>
  </property>
</bean>

<aop:config>
  <aop:aspect ref="trackCounter">
    <aop:pointcut id="trackPlayed" expression="execution(* soundsystem.CompactDisc.playerTrack(int)) and args(trackNumber)" />
    <aop:before pointcut-ref="trackPlayed" method="countTrack" />
  </aop:aspect>
</aop:config>

註意:我們使用了前面相同的aop命名空間XML元素,它們會將POJO聲明為切面。唯一的區別是切點表達式中包含了一個參數,這個參數會傳遞到通知的方法中。

4、通過切面引入新功能

<aop:aspect>
  <aop:declare-parents types-matching="concert.Performance" implement-interface="concert.Encoreable" default-impl="concert.DefaultEncoreable" />
</aop:aspect>

<aop:declare-parents>聲明了此切面所通知的bean要在它的對象層次結構擁有新的父類型。具體到本例中,類型匹配Performance接口(由types-matching屬性指定)的那些bean在父類結構中會增加Encoreable接口(由implement-interface屬性指定)。

二、註入Aspect切面

當springAOP不能滿足需求時,我們必須轉向更為強大的AspectJ。這裏主要註意的是如何使用spring為AspectJ 切面註入依賴。這裏就不寫了,我感覺一般也用不到,用到的時候在補充吧。。。

六、面向切面的spring(2)