• 第四章 面向切面的Spring


    4.1 什么是面向切面编程

      横切关注点可以被模块化为特殊的类,这些类被称为切面。

      好处:1关注点集中在一处,不是分散在多处代码中;2服务(主要的业务)模块更简洁,他们只包含主要关注点(或核心功能)的代码,次要关注点的代码被转移到切面中了;

    4.1.1 定义AOP术语

      术语:通知(advice),切点(pointcut)和连接点(join point);

      

      通知(advice)定义了切面是什么以及何时使用(定义切面是“什么”及“何时”)。

    • Before——在方法被调用之前调用通知
    • After——在方法完成之后
    • after-returning——在方法成功执行之调用通知
    • after-throwing——在方法抛出异常后调用通知
    • Around——通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

     连接点(Joinpoint):是在应用执行过程中能够插入切面的一个点。这个点可以是调用的方法时,抛出异常时,修改一个字段时(是一个时机),切面代码可以利用这些点插入到应用的正常流程之中,添加新的行为。

      切点(Pointcut):匹配通知所要织入的一个或多个连接点(定义切面在“何处”)

        切面(Aspect):是通知和切点的结合,通知和切点共同定义了关于切面的全部内容——是什么,何时、何处完成其功能;

      织入(Weaving):是将切面引用到目标对象来创建新的dialing对象的过程,切面在指定的连接点被织入到目标对象中。在目标对象的生命周期中有多个点可以进行织入。

    • 编译期——切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译期就是以这种方式织入切面的。
    • 类加载期——切面子啊目标被加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入引用之前增强该目标类的字节码。AspectJ5的LTW(load-time weaving)就支持以这种方式织入。
    • 运行期——切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。SpringAOP就是以这种方式织入切面的

    4.1.2 Spring对AOP的支持

      spring提供了4中AOP支持:

    • 基于代理的经典AOP(这本书中不介绍);
    • @AspectJ注解驱动的切面
    • 纯POJO切面
    • 注入式AspectJ切面(适合spring个版本)

      前三种都是Spring基于代理的AOP变体,因此Spring对AOP的支持局限于方法拦截。若是AOP需求超过了简单方法的拦截的范凑,那么考虑在AspectJ里实现切面,利用Spring的DI把Spring Bean注入到AspectJ切面中。

    4.2 使用切点选择连接点

      略过。。。

    4.3 在xml中声明切面

    4.3.1 声明前置通知和后置通知

      声明切面,我们先创建一个观众的Audience切面类:

     1 package com.springinaction.springidol;
     2 
     3 /**
     4  * 
     5  * @ClassName: Audience 
     6  * @Description: 观众的切面类
     7  * @author mao
     8  * @date 2017年3月23日 下午4:07:01 
     9  *
    10  */
    11 public class Audience {
    12     
    13     public void takeSeats(){
    14         //表演之前
    15         System.out.println("观众开始入座!");
    16     }
    17     
    18     public void turnOffCellPhones(){
    19         //表演之前
    20         System.out.println("观众正在坐着");
    21     }
    22     
    23     public void applaud(){
    24         //表演之后
    25         System.out.println("表演完后,鼓掌!鼓掌!鼓掌!");
    26     }
    27     
    28     public void demandRefund(){
    29         //表演失败之后
    30         System.out.println("表演失败,我们要退钱!");
    31     }
    32     
    33     
    34     
    35 }
    View Code

      首先,pom.xml文件中引入spring.aspects.jar文件

    1 <!-- spring aspects依赖,AOP用到 -->
    2  <dependency>
    3       <groupId>org.springframework</groupId>
    4       <artifactId>spring-aspects</artifactId>
    5       <version>4.2.9.RELEASE</version>
    6 </dependency>
    View Code

      其次,springbean.xml文件中<beans>标签中需要引入aop的命名空间 :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.0.xsd"

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop="http://www.springframework.org/schema/aop" 
     6     xmlns:p="http://www.springframework.org/schema/p"
     7     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     8         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     9         http://www.springframework.org/schema/context
    10         http://www.springframework.org/schema/context/spring-context-4.0.xsd
    11         http://www.springframework.org/schema/aop 
    12         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    13     
    14      
    15      <!--观众的bean  -->
    16      <bean id="audience"
    17              class="com.springinaction.springidol.Audience"></bean>
    18      <context:component-scan 
    19         base-package="com.springinaction.springidol"></context:component-scan>
    20      
    21      <!-- 声明aop -->
    22      <!-- 
    23           <aop:config>顶层的AOP配置元素,大多数<aop:*>都包在这个元素内
    24       -->
    25      <aop:config>
    26          <!-- 引用audience Bean
    27              <aop:aspect>定义切面的元素
    28           -->
    29          <aop:aspect ref="audience">
    30              
    31              <!-- 表演之前 -->
    32              <!-- <aop:before>定义aop前置通知 
    33                  pointcut=""是切点表达式,和method=""一起用,告诉通知切点在哪
    34                  整个标签表达出 在哪个类的那个方法执行什么通知
    35              -->
    36              <aop:before 
    37                  pointcut="execution(* com.springinaction.springidol.Performer.perform(..))" method="takeSeats"/>
    38              
    39              <!-- 表演之后  --> 
    40             <aop:before 
    41                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
    42                  method="turnOffCellPhones"/>             
    43              
    44              <!-- 表演之后 -->
    45              <!-- <aop:after-returning>定义aop返回通知 -->
    46              <aop:after-returning
    47                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
    48                  method="applaud"/>             
    49              
    50              <!-- 表演失败之后 -->
    51              <!-- <aop:after-throwing>定义aop异常通知 -->
    52              <aop:after-throwing 
    53                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
    54                  method="demandRefund"/>            
    55          
    56          </aop:aspect>
    57      </aop:config>
    58     
    59      
    60      
    61      
    62     
    63 </beans>
    View Code
     1 package com.springinaction.springidol;
     2 
     3 import javax.inject.Inject;
     4 
     5 import javax.inject.Named;
     6 
     7 import org.springframework.beans.factory.annotation.Autowired;
     8 import org.springframework.beans.factory.annotation.Qualifier;
     9 import org.springframework.beans.factory.annotation.Value;
    10 import org.springframework.stereotype.Component;
    11 
    12 
    13 
    14 /**
    15  * 
    16 * @ClassName: Instrumentalist 
    17 * @Description: 一个有天赋的音乐家
    18 * @author mao
    19 * @date 2017年3月19日 下午7:15:17 
    20 *
    21  */
    22 //将该类注册到Spring容器中,显示的为其命名为kenny。即ID为kenny
    23 @Component("kenny")
    24 public class Instrumentalist implements Performer {
    25     
    26     @Value("演员---薛之谦")
    27     private String song;
    28     
    29     @Autowired
    30     @Qualifier("saxophone")
    31     private Instrument instrument;
    32     
    33     //注入乐器
    34     public void setInstrument(Instrument instrument) {
    35         this.instrument = instrument;
    36     }
    37     public Instrument getInstrument() {
    38         return instrument;
    39     }
    40     //注入歌曲
    41     public void setSong(String song) {
    42         this.song = song;
    43     }
    44     public String getSong() {
    45         return song;
    46     }
    47     
    48     public Instrumentalist(){
    49         
    50     }
    51 
    52     public void perform() throws Exception {
    53 //        int i = 3/0;
    54         System.out.println("Playing "+song+": ");
    55     }
    56 
    57 }
    View Code

    测试:

     1 package com.springinaction.test;
     2 
     3 import org.junit.Test;
     4 
     5 
     6 import org.springframework.context.ApplicationContext;
     7 import org.springframework.context.support.ClassPathXmlApplicationContext;
     8 
     9 import com.springinaction.springidol.Auditorium;
    10 import com.springinaction.springidol.Instrumentalist;
    11 import com.springinaction.springidol.OneManBand;
    12 import com.springinaction.springidol.Performer;
    13 import com.springinaction.springidol.PoeticJuggler;
    14 import com.springinaction.springidol.Stage;
    15 import com.springinaction.springidol.Ticket;
    16 
    17 
    18 public class TestCase {
    19     
    20     //这个ClassPathXmlApplicationContext是springframe-context中
    21     //org.springframework.context.support包下的类
    22     ApplicationContext ac = new ClassPathXmlApplicationContext("spring/springbean.xml");//注意路径
    23     
    24     //测试声明式的切面、通知
    25     @Test
    26     public void testAspect() throws Exception {
    27         
    28         Performer kenny = (Performer) ac.getBean("kenny");
    29 //        System.out.println(kenny);
    30          
    31         kenny.perform();//输出 Playing 演员——薛之谦: 
    32 
    33         
    34         
    35     }
    36 
    37     
    38 }
    View Code

    结果:

    测试异常通知在Instrumentalist 的perform()方法中的int i=3/0注释解封,结果:

    这里要注意的是,这里的aop使用的是JDK的动态代理,因为Instrumentalist是实现了Perfromer的类,这个是JDK动态代理的条件吧,spring AOP还有个cglib代理,这个是通过创建一个类的子类来获得一个代理(这个子类是底层完成的),两者有区别,这里不详细说了(默认是使用JDK动态代理,若是满足不了JDK动态代理的条件,那就启用cglib代理)。

       上述的springbean.xml的aop配置还可以如下配置,简化一下代码:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop="http://www.springframework.org/schema/aop" 
     6     xmlns:p="http://www.springframework.org/schema/p"
     7     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     8         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     9         http://www.springframework.org/schema/context
    10         http://www.springframework.org/schema/context/spring-context-4.0.xsd
    11         http://www.springframework.org/schema/aop 
    12         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    13     
    14      
    15      <!--观众的bean  -->
    16      <bean id="audience"
    17              class="com.springinaction.springidol.Audience"></bean>
    18      <!--注解形式的 组件扫描 -->
    19      <context:component-scan 
    20         base-package="com.springinaction.springidol"></context:component-scan>
    21      
    22      <!-- 声明aop -->
    23      <!-- 
    24           <aop:config>顶层的AOP配置元素,大多数<aop:*>都包在这个元素内
    25       -->
    26     <!--  <aop:config>
    27          引用audience Bean
    28              <aop:aspect>定义切面的元素
    29          
    30          <aop:aspect ref="audience">
    31              
    32              表演之前
    33              <aop:before>定义aop前置通知 
    34                  pointcut=""是切点表达式,和method=""一起用,告诉通知切点在哪
    35                  整个标签表达出 在哪个类的那个方法执行什么通知
    36              
    37              <aop:before 
    38                  pointcut="execution(* com.springinaction.springidol.Performer.perform(..))" method="takeSeats"/>
    39              
    40              表演之后  
    41             <aop:before 
    42                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
    43                  method="turnOffCellPhones"/>             
    44              
    45              表演之后
    46              <aop:after-returning>定义aop返回通知
    47              <aop:after-returning
    48                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
    49                  method="applaud"/>             
    50              
    51              表演失败之后
    52              <aop:after-throwing>定义aop异常通知
    53              <aop:after-throwing 
    54                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
    55                  method="demandRefund"/>            
    56          
    57          </aop:aspect>
    58      </aop:config> -->
    59     
    60      <!-- 上面配置aop的切点表达式是一样的,所以可以写成如下配置 -->
    61      <aop:config>
    62          <!-- 引用audience Bean -->
    63          <aop:aspect ref="audience">
    64              <!-- 定义切点表达式 -->
    65              <aop:pointcut id="performance" expression="execution(* com.springinaction.springidol.Performer.perform(..))" />
    66              <!-- 表演之前-->
    67             <aop:before 
    68                 pointcut-ref="performance"
    69                  method="takeSeats"/>
    70              <!-- 表演之前-->
    71             <aop:before 
    72                 pointcut-ref="performance"
    73                  method="turnOffCellPhones"/>             
    74              <!-- 
    75              表演之后
    76              <aop:after-returning>定义aop返回通知 -->
    77              <aop:after-returning
    78                 pointcut-ref="performance"
    79                  method="applaud"/>             
    80              
    81              <!-- 表演失败之后
    82              <aop:after-throwing>定义aop异常通知 -->
    83              <aop:after-throwing 
    84                 pointcut-ref="performance"
    85                  method="demandRefund"/>            
    86          
    87          </aop:aspect>
    88      </aop:config>
    89      
    90     
    91 </beans>
    View Code

    4.3.2 声明环绕通知

    在Audience类中增加如下的方法:

     1 //环绕通知
     2     public void watchPerformance(ProceedingJoinPoint joinpoint){
     3         try {
     4             System.out.println("观众正在坐在自己的位置上---表演之前");
     5             System.out.println("观众关闭他们的手机---表演之前");
     6             long start = System.currentTimeMillis();
     7             
     8             joinpoint.proceed();
     9             
    10             long end=System.currentTimeMillis();
    11             
    12             System.out.println("表演很精彩,大家鼓掌....");
    13             System.out.println("表演耗时:"+(end-start)+"毫秒");
    14             
    15         } catch (Throwable e) {
    16             //表演失败,
    17             System.out.println("太糟糕了,我们要退钱!");
    18         }
    19         
    20         
    21     }
    View Code
     1 <!-- 上面配置aop的切点表达式是一样的,所以可以写成如下配置 -->
     2      <aop:config>
     3          <!-- 引用audience Bean -->
     4          <aop:aspect ref="audience">
     5              <!-- 定义切点表达式 -->
     6              <aop:pointcut id="performance" expression="execution(* com.springinaction.springidol.Performer.perform(..))" />
     7              <!-- 表演之前-->
     8             <!-- <aop:before 
     9                 pointcut-ref="performance"
    10                  method="takeSeats"/> -->
    11              <!-- 表演之前-->
    12             <!-- <aop:before 
    13                 pointcut-ref="performance"
    14                  method="turnOffCellPhones"/>     -->         
    15              <!-- 
    16              表演之后
    17              <aop:after-returning>定义aop返回通知 -->
    18              <!-- <aop:after-returning
    19                 pointcut-ref="performance"
    20                  method="applaud"/>      -->        
    21              
    22              <!-- 表演失败之后
    23              <aop:after-throwing>定义aop异常通知 -->
    24              <!-- <aop:after-throwing 
    25                 pointcut-ref="performance"
    26                  method="demandRefund"/>     -->        
    27              
    28              <!-- 环绕通知 
    29                  将其他通知都注释
    30              -->
    31              <aop:around 
    32                  pointcut-ref="performance"
    33                  method="watchPerformance"/>
    34          </aop:aspect>
    35      </aop:config>
    View Code

     为了看出表演耗时的时间,在perform()方法中加Thread.sleep(1000)(加不加无所谓的)睡1秒;

    结果:

    4.3.3 为通知传递参数

      直接上一个读心者的例子,先创建几个类:

     1 package com.springinaction.springidol;
     2 
     3 /**
     4  * 读心者类
     5  * @ClassName: MindReader 
     6  * @Description: 可以读取别人的思想
     7  * @author mao
     8  * @date 2017年3月23日 下午5:23:49 
     9  *
    10  */
    11 public interface MindReader {
    12     
    13     //拦截别人的想法(感应别人的内心想法)
    14     void interceptThoughts(String thoughts);
    15     
    16     //获得想法
    17     String getThoughts();
    18 }
    View Code
     1 package com.springinaction.springidol;
     2 
     3 /**
     4  * 读心者的实现类
     5  * @ClassName: Magician 
     6  * @Description: 可以读取别人想法的具体实例
     7  * @author mao
     8  * @date 2017年3月23日 下午5:29:12 
     9  *
    10  */
    11 public class Magician implements MindReader {
    12     
    13     
    14     private String thoughts;
    15     
    16     public void interceptThoughts(String thoughts) {
    17         
    18         System.out.println("感应志愿者的想法!");
    19         this.thoughts = thoughts;
    20 
    21     }
    22 
    23     public String getThoughts() {
    24         
    25         return thoughts;
    26     }
    27 
    28 }
    View Code
     1 package com.springinaction.springidol;
     2 
     3 /**
     4  * 思考者的接口
     5  * @ClassName: Thinker 
     6  * @Description: 沉思者 
     7  * @author mao
     8  * @date 2017年3月23日 下午5:30:07 
     9  *
    10  */
    11 public interface Thinker {
    12     //瞎想
    13     void thinkOfSomething(String thoughts);
    14 }
    View Code
     1 package com.springinaction.springidol;
     2 
     3 /**
     4  * 沉思者
     5  * @ClassName: Volunteer 
     6  * @Description: 一个时代的思想家
     7  * @author mao
     8  * @date 2017年3月23日 下午5:31:58 
     9  *
    10  */
    11 public class Volunteer implements Thinker {
    12     
    13     private String thoughts;
    14     
    15     public void thinkOfSomething(String thoughts) {
    16         
    17         this.thoughts = thoughts;
    18 
    19     }
    20 
    21     public String getThoughts() {
    22         return thoughts;
    23     }
    24     
    25 }
    View Code

    xml的配置(晕倒,在切点表达式中把thoughts写错了,找了老半天的错误) arg()限制连接点匹配参数为指定类型的执行方法:

      1 <?xml version="1.0" encoding="UTF-8"?>
      2 <beans xmlns="http://www.springframework.org/schema/beans"
      3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      4     xmlns:context="http://www.springframework.org/schema/context"
      5     xmlns:aop="http://www.springframework.org/schema/aop" 
      6     xmlns:p="http://www.springframework.org/schema/p"
      7     xsi:schemaLocation="http://www.springframework.org/schema/beans 
      8         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
      9         http://www.springframework.org/schema/context
     10         http://www.springframework.org/schema/context/spring-context-4.0.xsd
     11         http://www.springframework.org/schema/aop 
     12         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
     13     
     14      
     15      <!--观众的bean  -->
     16     <bean id="audience"
     17              class="com.springinaction.springidol.Audience"></bean>
     18      <!--注解形式的 组件扫描 -->
     19      <context:component-scan 
     20         base-package="com.springinaction.springidol"></context:component-scan>
     21      
     22      <!-- 声明aop -->
     23      <!-- 
     24           <aop:config>顶层的AOP配置元素,大多数<aop:*>都包在这个元素内
     25       -->
     26     <!--  <aop:config>
     27          引用audience Bean
     28              <aop:aspect>定义切面的元素
     29          
     30          <aop:aspect ref="audience">
     31              
     32              表演之前
     33              <aop:before>定义aop前置通知 
     34                  pointcut=""是切点表达式,和method=""一起用,告诉通知切点在哪
     35                  整个标签表达出 在哪个类的那个方法执行什么通知
     36              
     37              <aop:before 
     38                  pointcut="execution(* com.springinaction.springidol.Performer.perform(..))" method="takeSeats"/>
     39              
     40              表演之后  
     41             <aop:before 
     42                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
     43                  method="turnOffCellPhones"/>             
     44              
     45              表演之后
     46              <aop:after-returning>定义aop返回通知
     47              <aop:after-returning
     48                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
     49                  method="applaud"/>             
     50              
     51              表演失败之后
     52              <aop:after-throwing>定义aop异常通知
     53              <aop:after-throwing 
     54                 pointcut="execution(* com.springinaction.springidol.Performer.perform(..))"
     55                  method="demandRefund"/>            
     56          
     57          </aop:aspect>
     58      </aop:config> -->
     59      
     60      
     61      <!-- 上面配置aop的切点表达式是一样的,所以可以写成如下配置 -->
     62      <aop:config>
     63          <!-- 引用audience Bean -->
     64          <aop:aspect ref="audience">
     65              <!-- 定义切点表达式 -->
     66              <aop:pointcut id="performance" expression="execution(* com.springinaction.springidol.Performer.perform(..))" />
     67              <!-- 表演之前-->
     68             <!-- <aop:before 
     69                 pointcut-ref="performance"
     70                  method="takeSeats"/> -->
     71              <!-- 表演之前-->
     72             <!-- <aop:before 
     73                 pointcut-ref="performance"
     74                  method="turnOffCellPhones"/>     -->         
     75              <!-- 
     76              表演之后
     77              <aop:after-returning>定义aop返回通知 -->
     78              <!-- <aop:after-returning
     79                 pointcut-ref="performance"
     80                  method="applaud"/>      -->        
     81              
     82              <!-- 表演失败之后
     83              <aop:after-throwing>定义aop异常通知 -->
     84              <!-- <aop:after-throwing 
     85                 pointcut-ref="performance"
     86                  method="demandRefund"/>     -->        
     87              
     88              <!-- 环绕通知 
     89                  将其他通知都注释
     90              -->
     91              <aop:around 
     92                  pointcut-ref="performance"
     93                  method="watchPerformance"/>
     94          </aop:aspect> 
     95          
     96          <aop:aspect ref="magician">
     97              <aop:pointcut 
     98                  id="thinking"
     99                  expression="execution(* com.springinaction.springidol.Thinker.thinkOfSomething(String)) and args(thoughts)" />
    100              
    101              <aop:before 
    102                  pointcut-ref="thinking" 
    103                  method="interceptThoughts" 
    104                  arg-names="thoughts"/>
    105          
    106          </aop:aspect>
    107      </aop:config>
    108      
    109      <bean id="volunteer" class="com.springinaction.springidol.Volunteer"></bean>
    110      <bean id="magician" class="com.springinaction.springidol.Magician"></bean>
    111     
    112 </beans>
    View Code

    测试代码:

     1 //测试传入参数的通知
     2     @Test
     3     public void testArgsAdvisor() throws Exception {
     4         
     5         //思考者,先思考
     6         Thinker volunteer = (Thinker) ac.getBean("volunteer");
     7         volunteer.thinkOfSomething("你猜我想啥?");
     8         
     9         //读心者 对他想的啥
    10         MindReader magician = (MindReader) ac.getBean("magician");
    11         System.out.println(magician.getThoughts());
    12 
    13     }
    View Code

    结果:

    4.4 注解切面

     注解使用:

     1 package com.springinaction.springidol;
     2 
     3 import org.aspectj.lang.ProceedingJoinPoint;
     4 import org.aspectj.lang.annotation.After;
     5 import org.aspectj.lang.annotation.AfterReturning;
     6 import org.aspectj.lang.annotation.AfterThrowing;
     7 import org.aspectj.lang.annotation.Around;
     8 import org.aspectj.lang.annotation.Aspect;
     9 import org.aspectj.lang.annotation.Before;
    10 import org.aspectj.lang.annotation.Pointcut;
    11 import org.springframework.stereotype.Component;
    12 
    13 /**
    14  * 
    15  * @ClassName: Audience 
    16  * @Description: 观众的切面类
    17  * @author mao
    18  * @date 2017年3月23日 下午4:07:01 
    19  *
    20  */
    21 @Component//这个不要忘了,注解的自动扫描 会将其加入到IOC容器中
    22 @Aspect
    23 public class Audience {
    24     
    25     //定义一个可以在@AspectJ切面内可重用的切点
    26     @Pointcut("execution(* com.springinaction.springidol.Performer.perform(..))")
    27     public void performance(){
    28         
    29     }
    30     
    31     
    32     @Before("performance()")
    33     public void takeSeats(){
    34         //表演之前
    35         System.out.println("观众开始入座!");
    36     }
    37     
    38     @Before("performance()")
    39     public void turnOffCellPhones(){
    40         //表演之前
    41         System.out.println("观众正在坐着");
    42     }
    43     
    44     @AfterReturning("performance()")
    45     public void applaud(){
    46         //表演之后
    47         System.out.println("表演完后,鼓掌!鼓掌!鼓掌!");
    48     }
    49     
    50     @AfterThrowing("performance()")
    51     public void demandRefund(){
    52         //表演失败之后
    53         System.out.println("表演失败,我们要退钱!");
    54     }
    55     
    56     //环绕通知
    57     @Around("performance()")
    58     public void watchPerformance(ProceedingJoinPoint joinpoint){
    59         try {
    60             System.out.println("观众正在坐在自己的位置上---表演之前");
    61             System.out.println("观众关闭他们的手机---表演之前");
    62             long start = System.currentTimeMillis();
    63             
    64             joinpoint.proceed();
    65             
    66             long end=System.currentTimeMillis();
    67             
    68             System.out.println("表演很精彩,大家鼓掌....");
    69             System.out.println("表演耗时:"+(end-start)+"毫秒");
    70             
    71         } catch (Throwable e) {
    72             //表演失败,
    73             System.out.println("太糟糕了,我们要退钱!");
    74         }
    75         
    76         
    77     }
    78     
    79     
    80 }
    View Code
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop="http://www.springframework.org/schema/aop" 
     6     xmlns:p="http://www.springframework.org/schema/p"
     7     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     8         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     9         http://www.springframework.org/schema/context
    10         http://www.springframework.org/schema/context/spring-context-4.0.xsd
    11         http://www.springframework.org/schema/aop 
    12         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    13     
    14  
    15      <!--注解形式的 组件扫描 -->
    16      <context:component-scan 
    17         base-package="com.springinaction.springidol"></context:component-scan>
    18      <!--使用@AspectJ注解作为指引来创建给予代理的切面,就是把他编程切面,这个@AspectJ类中的有且点表达式和通知  -->
    19     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    20     
    21     
    22     
    23 </beans>
    View Code

    测试结果(测试用例之前写过):

    这本书中错误还不少,不过不妨碍阅读:<aop:aspectj-autoproxy> 红色写成了aespectj,还有前面有一个写环绕通知的时候,method="watchPerformance()";括弧是不需要的。

    4.5 注入AspectJ切面

       表示看不懂。。。

    源码下载地址

  • 相关阅读:
    从首页看CCS布局
    Community Server专题一:概述Community Server
    datagrid程序增加列的方法
    类的关键字
    base 关键字用于从派生类中访问基类的成员:
    关于CS1.1后台管理页面的研究
    如何:创建同步 HTTP 处理程序
    Community Server专题二:体系结构
    SqlTransaction 类
    单继承与多实现
  • 原文地址:https://www.cnblogs.com/huaxueyihao/p/6597268.html
Copyright © 2020-2023  润新知