面向切面的spring

Posted ssc在路上

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向切面的spring相关的知识,希望对你有一定的参考价值。

  这个是承接五的,这部分主要的内容是在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的主要内容,如果未能解决你的问题,请参考以下文章

面向切面的Spring

面向切面的Spring

面向切面的spring

Spring系列Spring中AOP面向切面的编程(动态代理)

面向切面的Spring

面向切面的Spring