最近在看spring in action 4,为了巩固切面知识,参考了书上的知识写了这个Demo.留着以后复习
业务场景是观众观看演出:
将演出视为一个切点.那么观众就是一个切面.演出开始前观众需要将手机调整为静音并就坐,演出如果顺利结束观众会鼓掌喝彩,演出如果出现了问题,观众就会要求退票.
在程序中来思考的话也就是:
指定在演出这个方法执行前必须先执行观众的手机调整静音和就坐方法.
如果演出方法顺利执行完成了.就执行观众的鼓掌喝彩方法,
如果演出方法抛出了异常,就需要执行观众的退票方法
1.首先创建一个切点
package concert;
/**
* 切点
* @author CCC
*
*/
public interface Performance {
public void perform();
}
2.创建表演的实现类
package concert;
import java.util.Random;
import org.springframework.stereotype.Component;
@Component
public class BiaoYan implements Performance {
@Override
public void perform() {
Random ran = new Random();
int i = ran.nextInt(2);
int j = ran.nextInt(3);
System.out.println("表演开始啦!!!");
if(j == 0){
System.out.println("今天的表演是-白雪公主与七矮人");
}else if(j == 1){
System.out.println("今天的表演是-白毛女");
}else{
System.out.println("今天的表演是-孟姜女哭长城");
}
if(i == 0){
System.out.println("表演完美结束");
}else if(i == 1){
System.out.println("表演出现问题");
throw new RuntimeException();
}
}
}
3.创建切面
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;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* 观看演出的切面
* @author CCC
*
*/
@Aspect // 表示该类将作为一个切面
@Component
public class Audience {
/*抽取出一个切点用来重用
*
* 定义一个切点,此处的切点意味着
* 不关心该方法的返回值,也不指定传入的参数,
* 只要调用该方法之前都会拦截并执行本切面中的方法
*
* ** 表示不关心返回值类型
* concert.Performance 切点方法所属的类
* perform 切点
* (..) 使用任意参数
*/
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance(){}
/**
* 表演开始前要将手机调成静音-切点方法执行前
*/
@Before("performance()") // 指向上面定义的切点
// @Before("execution(** concert.Performance.perform(..))") // 也可以直接重新定义切点方法
public void silenceCellPhones(){
System.out.println("手机静音!");
}
@Before("performance()")
public void takeSeats(){
System.out.println("观众就坐!");
}
/**
* 表演结束后-切点方法执行结束后
*/
@AfterReturning("performance()")
public void applause(){
System.out.println("鼓掌,喝彩!");
}
/**
* 表演失败-切点方法抛出异常
*/
@AfterThrowing("performance()")
public void demanRefund(){
System.out.println("要求退票!");
}
}
4.创建配置类来启用切点和切面,并让spring 来自动装配bean
package concert;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* 切面配置类 - 启用AspectJ 注解的自动代理
* @author CCC
*
*/
@Configuration // 表示为配置类Bean
@EnableAspectJAutoProxy // 启用 AspectJ自动代理
@ComponentScan // 启用自动扫描 默认为同一个包下的类
public class ConcertConfig {
}
5.最后创建一个测试类来测试
package concert;
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;
//运行时自动创建 Spring 的应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
//指定在 CDPlayerConfig 中加载配置
@ContextConfiguration(classes = ConcertConfig.class)
public class ConertTest {
@Autowired
private Performance pc;
@Test
public void test1(){
for(int i=0;i<5;i++){
pc.perform();
System.out.println("-----------------------------");
}
}
}
测试结果:
手机静音!
观众就坐!
表演开始啦!!!
今天的表演是-孟姜女哭长城
表演完美结束
鼓掌,喝彩!
-----------------------------
手机静音!
观众就坐!
表演开始啦!!!
今天的表演是-白毛女
表演出现问题
要求退票!