PS:定义切面
package concert;
import org.aspectj.lang.annotation.*;
@Aspect
public class Audience {
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance() {}
@Before("performance()")
public void silenceCellPhones() {
System.out.println("Silencing cell phones");
}
@Before("performance()")
public void takeSeats() {
System.out.println("Taking seats");
}
@AfterReturning("performance()")
public void applause() {
System.out.println("CLAP CLAP CLAP!!!");
}
@AfterThrowing("performance()")
public void demandRefund() {
System.out.println("Demanding a refund");
}
}
PS:Java配置,@EnableAspectJAutoProxy启用AspectJ自动代理
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();
}
}
PS:切点接口
package concert;
public interface Performance {
public void perform();
}
PS:切点接口实现
package concert;
import org.springframework.stereotype.Component;
@Component
public class PerformanceImpl implements Performance {
public void perform() {
System.out.println("Singing!!!");
}
}
PS:如果通过XML装配bean
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="concert"/>
<aop:aspectj-autoproxy />
<bean class="concert.Audience" />
beans>
import concert.ConcertConfig;
import concert.Performance;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ConcertConfig.class)
public class PerformanceTest {
@Autowired
private Performance performance;
@Test
public void perform() {
performance.perform();
}
}
PS:把上面的切面代码改为如下。
package concert;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class Audience {
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance() {}
@Around("performance()")
public void watchPerformance(ProceedingJoinPoint jp) {
try {
System.out.println("Silencing cell phones");
System.out.println("Taking seats");
jp.proceed();
System.out.println("CLAP CLAP CLAP!!!");
} catch (Throwable e) {
System.out.println("Demanding a refund");
}
}
}
package soundsystem;
import java.util.List;
public class BlankDisc implements CompactDisc {
private String title;
private String artist;
private List tracks;
public void setTitle(String title) {
this.title = title;
}
public void setArtist(String artist) {
this.artist = artist;
}
public void setTracks(List tracks) {
this.tracks = tracks;
}
public void play() {
System.out.println("Playing "+title+" by "+artist);
for(String track : tracks) {
System.out.println("-Track: "+track);
}
}
public void playTrack(int trackNumber) {
System.out.println("Playing track"+trackNumber);
}
}
package soundsystem;
public interface CompactDisc {
public void play();
public void playTrack(int trackNumber);
}
package soundsystem;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import java.util.HashMap;
import java.util.Map;
@Aspect
public class TrackCounter {
private Map trackCounts = new HashMap();
@Pointcut("execution(* soundsystem.CompactDisc.playTrack(int)) "+"&& args(trackNumber)")
public void trackPlayed(int trackNumber) {}
@Before("trackPlayed(trackNumber)")
public void countTrack(int trackNumber) {
int currentCount = getPlayCount(trackNumber);
trackCounts.put(trackNumber, currentCount+1);
}
public int getPlayCount(int trackNumber) {
return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0;
}
}
package soundsystem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableAspectJAutoProxy
public class TrackCounterConfig {
@Bean
public CompactDisc sgtPeppers() {
BlankDisc cd = new BlankDisc();
cd.setTitle("hello");
cd.setArtist("world");
List tracks = new ArrayList();
tracks.add("11111");
tracks.add("22222");
tracks.add("33333");
tracks.add("44444");
tracks.add("55555");
cd.setTracks(tracks);
return cd;
}
@Bean
public TrackCounter trackCounter() {
return new TrackCounter();
}
}
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import soundsystem.CompactDisc;
import soundsystem.TrackCounter;
import soundsystem.TrackCounterConfig;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= TrackCounterConfig.class)
public class TrackCounterTest {
@Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
@Autowired
private CompactDisc cd;
@Autowired
private TrackCounter counter;
@Test
public void testTrackCounter() {
cd.playTrack(1);
cd.playTrack(2);
cd.playTrack(3);
cd.playTrack(3);
cd.playTrack(3);
cd.playTrack(3);
cd.playTrack(7);
cd.playTrack(7);
assertEquals(1, counter.getPlayCount(1));
assertEquals(1, counter.getPlayCount(2));
assertEquals(4, counter.getPlayCount(3));
assertEquals(0, counter.getPlayCount(4));
assertEquals(0, counter.getPlayCount(5));
assertEquals(0, counter.getPlayCount(6));
assertEquals(2, counter.getPlayCount(7));
}
}
参考:Spring Aop 使用注解引入新功能
PS:不需要,没有用到
package concert;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class Audience {
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance() {}
@Around("performance()")
public void watchPerformance(ProceedingJoinPoint jp) {
try {
System.out.println("Silencing cell phones");
System.out.println("Taking seats");
jp.proceed();
System.out.println("CLAP CLAP CLAP!!!");
} catch (Throwable e) {
System.out.println("Demanding a refund");
}
}
}
PS:注入EncoreableIntroducer
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();
}
@Bean
public EncoreableIntroducer encoreableIntroducer() { return new EncoreableIntroducer(); }
}
PS:Encoreable实现类
package concert;
public class DefaultEncoreable implements Encoreable {
public void performEncore() {
System.out.println("performEncore!!!");
}
}
PS:Encoreable接口
package concert;
public interface Encoreable {
public void performEncore();
}
PS:EncoreableIntroducer切面,加号表示Performance所有子类型,不是Performance本身
package concert;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
@Aspect
public class EncoreableIntroducer {
@DeclareParents(value="concert.Performance+",defaultImpl = DefaultEncoreable.class)
public static Encoreable encoreable;
}
PS:Performance接口
package concert;
public interface Performance {
public void perform();
}
PS:Performance实现类
package concert;
import org.springframework.stereotype.Component;
@Component
public class PerformanceImpl implements Performance {
public void perform() {
System.out.println("Singing!!!");
}
}
import concert.ConcertConfig;
import concert.Encoreable;
import concert.Performance;
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(classes = ConcertConfig.class)
public class PerformanceTest {
@Autowired
private ApplicationContext context;
@Test
public void performEncore() {
//对象performanceImpl不仅有PerformanceImpl的功能,也有DefaultEncoreable类的功能
Encoreable encoreable = (Encoreable) context.getBean("performanceImpl");
encoreable.performEncore();
}
}
ref="audience">
id="performance" expression="execution(** concert.Performance.perform(..))"/>
before pointcut-ref="performance" method="silenceCellPhones" />
before pointcut-ref="performance" method="takeSeats" />
after-returning pointcut-ref="performance" method="applause" />
after-throwing pointcut-ref="performance" method="demandRefund" />
package concert;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
public class Audience {
public void silenceCellPhones() {
System.out.println("Silencing cell phones");
}
public void takeSeats() {
System.out.println("Taking seats");
}
public void applause() {
System.out.println("CLAP CLAP CLAP!!!");
}
public void demandRefund() {
System.out.println("Demanding a refund");
}
}
<aop:config>
<aop:aspect ref="audience">
<aop:pointcut id="performance" expression="execution(** concert.Performance.perform(..))"/>
<aop:around pointcut-ref="performance" method="watchPerformance"/>
aop:aspect>
aop:config>
package concert;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
public class Audience {
public void watchPerformance(ProceedingJoinPoint jp) {
try {
System.out.println("Silencing cell phones");
System.out.println("Taking seats");
jp.proceed();
System.out.println("CLAP CLAP CLAP!!!");
} catch (Throwable e) {
System.out.println("Demanding a refund");
}
}
}
package soundsystem;
import java.util.HashMap;
import java.util.Map;
public class TrackCounter {
private Map trackCounts = new HashMap();
public void countTrack(int trackNumber) {
int currentCount = getPlayCount(trackNumber);
trackCounts.put(trackNumber, currentCount+1);
}
public int getPlayCount(int trackNumber) {
return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0;
}
}
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="trackCounter" class="soundsystem.TrackCounter"/>
<bean id="cd" class="soundsystem.BlankDisc">
<property name="title" value="hello"/>
<property name="artist" value="world"/>
<property name="tracks">
<list>
<value>11111value>
<value>22222value>
<value>33333value>
<value>44444value>
<value>55555value>
list>
property>
bean>
<aop:config>
<aop:aspect ref="trackCounter">
<aop:pointcut id="trackPlayed" expression="execution(* soundsystem.CompactDisc.playTrack(int)) and args(trackNumber)"/>
<aop:before pointcut-ref="trackPlayed" method="countTrack"/>
aop:aspect>
aop:config>
beans>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="concert"/>
<aop:aspectj-autoproxy />
<bean id="audience" class="concert.Audience" />
<bean id="encorebleDelegate" class="concert.DefaultEncoreable"/>
<aop:config>
<aop:aspect ref="audience">
<aop:pointcut id="performance" expression="execution(** concert.Performance.perform(..))"/>
<aop:around pointcut-ref="performance" method="watchPerformance"/>
aop:aspect>
<aop:aspect>
<aop:declare-parents types-matching="concert.Performance+" implement-interface="concert.Encoreable" delegate-ref="encorebleDelegate"/>
aop:aspect>
aop:config>
beans>