SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-005-定义切面使用@Aspect、@EnableAspectJAutoProxy、<aop:aspectj-autoproxy>

一、

假设有如下情况,有一个演凑者和一批观众,要实现在演凑者的演凑方法前织入观众的"坐下"、"关手机方法",在演凑结束后,如果成功,则织入观众"鼓掌",演凑出错则观众要求"回水"

基本的类如下:

1.

package com.springinaction.springidol;

public interface Instrument {
  public void play();
}

2.

1 package com.springinaction.springidol;
2 
3 public class Guitar implements Instrument {
4   public void play() {
5     System.out.println("Strum strum strum");
6   }
7 }

 

3.

package com.springinaction.springidol;

public interface Performer {
  void perform() throws PerformanceException;
}

4.

 1 package com.springinaction.springidol;
 2 
 3 public class Instrumentalist implements Performer {
 4   public void perform() throws PerformanceException {
 5     instrument.play();
 6   }
 7 
 8   private Instrument instrument;
 9 
10   public void setInstrument(Instrument instrument) {
11     this.instrument = instrument;
12   }
13 
14   public Instrument getInstrument() {
15     return instrument;
16   }
17 }

 

 

二、

可以定义的advice

Spring的切面是一个pojo

1.使用@Aspect定义切面类

(1)不同的方法可以用不同的pointcut

 1 package concert;
 2 import org.aspectj.lang.annotation.AfterReturning;
 3 import org.aspectj.lang.annotation.AfterThrowing;
 4 import org.aspectj.lang.annotation.Aspect;
 5 import org.aspectj.lang.annotation.Before;
 6 @Aspect
 7 public class Audience {
 8     @Before("execution(** concert.Performance.perform(..))")
 9     public void silenceCellPhones() {
10         System.out.println("Silencing cell phones");
11     }
12     @Before("execution(** concert.Performance.perform(..))")
13     public void takeSeats() {
14         System.out.println("Taking seats");
15     }
16     @AfterReturning("execution(** concert.Performance.perform(..))")
17     public void applause() {
18         System.out.println("CLAP CLAP CLAP!!!");
19     }
20     @AfterThrowing("execution(** concert.Performance.perform(..))")
21     public void demandRefund() {
22         System.out.println("Demanding a refund");
23     }
24 }

(2)定义一个公共的pointcut,其对应的方法名就是id

 1 package com.springinaction.springidol;
 2 
 3 import org.aspectj.lang.annotation.AfterReturning;
 4 import org.aspectj.lang.annotation.AfterThrowing;
 5 import org.aspectj.lang.annotation.Aspect;
 6 import org.aspectj.lang.annotation.Before;
 7 import org.aspectj.lang.annotation.Pointcut;
 8 
 9 @Aspect
10 public class Audience {
11   @Pointcut(
12         "execution(* com.springinaction.springidol.Performer.perform(..))")
13   public void performance() { //<co id="co_definePointcut"/>
14   }
15 
16   @Before("performance()")
17   public void takeSeats() { //<co id="co_takeSeatsBefore"/>
18     System.out.println("The audience is taking their seats.");
19   }
20 
21   @Before("performance()")
22   public void turnOffCellPhones() { //<co id="co_turnOffCellPhonesBefore"/>
23     System.out.println("The audience is turning off their cellphones");
24   }
25 
26   @AfterReturning("performance()")
27   public void applaud() { //<co id="co_applaudAfter"/>
28     System.out.println("CLAP CLAP CLAP CLAP CLAP");
29   }
30 
31   @AfterThrowing("performance()")
32   public void demandRefund() { //<co id="co_demandRefundAfterException"/>
33     System.out.println("Boo! We want our money back!");
34   }
35 }

 

2.把切面交给Spring容器

(1)在java配置文件中,使用@EnableAspectJAutoProxy

 1 package concert;
 2 import org.springframework.context.annotation.Bean;
 3 import org.springframework.context.annotation.ComponentScan;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.context.annotation.EnableAspectJAutoProxy;
 6 @Configuration
 7 @EnableAspectJAutoProxy
 8 @ComponentScan
 9 public class ConcertConfig {
10     @Bean
11     public Audience audience() {
12         return new Audience();
13     }
14 }

(2)在xml使用<aop:aspectj-autoproxy>

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!--<start id="preamble" />--> 
 3 <beans xmlns="http://www.springframework.org/schema/beans"
 4  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5  xmlns:aop="http://www.springframework.org/schema/aop"
 6  xsi:schemaLocation="http://www.springframework.org/schema/beans 
 7      http://www.springframework.org/schema/beans/spring-beans.xsd
 8      http://www.springframework.org/schema/aop
 9      http://www.springframework.org/schema/aop/spring-aop.xsd">
10 <!--<end id="preamble" />-->
11 
12   <bean id="eddie"
13       class="com.springinaction.springidol.Instrumentalist">
14     <property name="instrument">
15       <bean class="com.springinaction.springidol.Guitar" />
16     </property>
17   </bean>
18 
19   <!--<start id="audience_bean" />--> 
20   <bean id="audience" 
21       class="com.springinaction.springidol.Audience" /> 
22   <!--<end id="audience_bean" />-->
23 
24   <!--<start id="contestant_introducer" />--> 
25   <bean class="com.springinaction.springidol.ContestantIntroducer" />
26   <!--<end id="contestant_introducer" />-->
27 
28   <!--<start id="aspectj_autoproxy" />--> 
29     <aop:aspectj-autoproxy />
30   <!--<end id="aspectj_autoproxy" />-->
31 
32 </beans>

 

3.测试

 

package com.springinaction.springidol;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("spring-idol.xml")
public class AspectTest {
  @Autowired
  ApplicationContext context;

  @Test
  public void audienceShouldApplaud() throws Exception {
    Performer eddie = (Performer) context.getBean("eddie");
    eddie.perform();
  }

  @Test
  public void eddieShouldBeAContestant() {
    Contestant eddie = (Contestant) context.getBean("eddie");
    eddie.receiveAward();
  }
}

 

audienceShouldApplaud的测试结果:

The audience is taking their seats.
The audience is turning off their cellphones
Strum strum strum
CLAP CLAP CLAP CLAP CLAP

 

posted @ 2016-03-03 17:43  shamgod  阅读(446)  评论(0编辑  收藏  举报
haha