一、
假設有如下情況,有一個演湊者和一批觀眾,要實現在演湊者的演湊方法前織入觀眾的"坐下"、"關手機方法",在演湊結束后,如果成功,則織入觀眾"鼓掌",演湊出錯則觀眾要求"回水"
基本的類如下:
1.
package com.springinaction.springidol; public interface Instrument { public void play(); }
2.
package com.springinaction.springidol; public class Guitar implements Instrument { public void play() { System.out.println("Strum strum strum"); } }
3.
package com.springinaction.springidol; public interface Performer { void perform() throws PerformanceException; }
4.
package com.springinaction.springidol; public class Instrumentalist implements Performer { public void perform() throws PerformanceException { instrument.play(); } private Instrument instrument; public void setInstrument(Instrument instrument) { this.instrument = instrument; } public Instrument getInstrument() { return instrument; } }
二、
可以定義的advice
Spring的切面是一個pojo
1.使用@Aspect定義切面類
(1)不同的方法可以用不同的pointcut
package concert; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class Audience { @Before("execution(** concert.Performance.perform(..))") public void silenceCellPhones() { System.out.println("Silencing cell phones"); } @Before("execution(** concert.Performance.perform(..))") public void takeSeats() { System.out.println("Taking seats"); } @AfterReturning("execution(** concert.Performance.perform(..))") public void applause() { System.out.println("CLAP CLAP CLAP!!!"); } @AfterThrowing("execution(** concert.Performance.perform(..))") public void demandRefund() { System.out.println("Demanding a refund"); } }
(2)定義一個公共的pointcut,其對應的方法名就是id
package com.springinaction.springidol; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class Audience { @Pointcut( "execution(* com.springinaction.springidol.Performer.perform(..))") public void performance() { //<co id="co_definePointcut"/> } @Before("performance()") public void takeSeats() { //<co id="co_takeSeatsBefore"/> System.out.println("The audience is taking their seats."); } @Before("performance()") public void turnOffCellPhones() { //<co id="co_turnOffCellPhonesBefore"/> System.out.println("The audience is turning off their cellphones"); } @AfterReturning("performance()") public void applaud() { //<co id="co_applaudAfter"/> System.out.println("CLAP CLAP CLAP CLAP CLAP"); } @AfterThrowing("performance()") public void demandRefund() { //<co id="co_demandRefundAfterException"/> System.out.println("Boo! We want our money back!"); } }
2.把切面交給Spring容器
(1)在java配置文件中,使用@EnableAspectJAutoProxy
package concert; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @EnableAspectJAutoProxy @ComponentScan public class ConcertConfig { @Bean public Audience audience() { return new Audience(); } }
(2)在xml使用<aop:aspectj-autoproxy>
<?xml version="1.0" encoding="UTF-8"?> <!--<start id="preamble" />--> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--<end id="preamble" />--> <bean id="eddie" class="com.springinaction.springidol.Instrumentalist"> <property name="instrument"> <bean class="com.springinaction.springidol.Guitar" /> </property> </bean> <!--<start id="audience_bean" />--> <bean id="audience" class="com.springinaction.springidol.Audience" /> <!--<end id="audience_bean" />--> <!--<start id="contestant_introducer" />--> <bean class="com.springinaction.springidol.ContestantIntroducer" /> <!--<end id="contestant_introducer" />--> <!--<start id="aspectj_autoproxy" />--> <aop:aspectj-autoproxy /> <!--<end id="aspectj_autoproxy" />--> </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