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

时间:2023-03-08 15:58:12

一、

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

基本的类如下:

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

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