一、
假设有如下情况,有一个演凑者和一批观众,要实现在演凑者的演凑方法前织入观众的"坐下"、"关手机方法",在演凑结束后,如果成功,则织入观众"鼓掌",演凑出错则观众要求"回水"
基本的类如下:
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