zoukankan      html  css  js  c++  java
  • 六、面向切面的spring(2)

      这个是承接五的,这部分主要的内容是在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 切面注入依赖。这里就不写了,我感觉一般也用不到,用到的时候在补充吧。。。

  • 相关阅读:
    AMQP协议
    设计模式三:行为型模式
    设计模式二:结构型模式
    设计模式一:创建型模式
    算法进阶
    数据结构
    希尔排序、计数排序、桶排序、基数排序
    归并排序
    python Gevent协程
    python——多进程
  • 原文地址:https://www.cnblogs.com/ssh-html/p/9747585.html
Copyright © 2011-2022 走看看