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
You can do anything you set your mind to, man!