首先随便写个方法,index静态变量的作用是便于验证抛异常情况。
@RestController
public class indexController {
private static int index =1;
@RequestMapping("/index")
public String index(String name,String age) throws Exception {
index++;
int i = index % 2;
if(i==1)throw new Exception("抛出异常");
System.out.println("index()");
return "Nice day-index()";
}
}
先简介一下注解
@Aspect - 定义一个切面,意思就是用这个注解的类,现在就是一个切面
@Component - spring的注解,意思是当前类交给spring容器来管理了。
@Poincut - 切入点,简单来说就是与你要作用的对象或方法所匹配上,execution( * *(..)),*代表任何,第一个* 代表返回值,意思任何返回值的方法,第二个*代表类名意思所有的类也可以精确到方法,(..),代表参数要是精确到参数就在()里定义 ..两个点代表任何参数。
例子中含义是,任何返回值 并且在com.hfl.web.controller.indexController类下的,叫index并且参数随意的方法。先看下例子在做通知的介绍。
@Aspect
@Component
public class LogAop {
@Pointcut("execution(* com.hfl.web.controller.indexController.index(..))")
public void aop(){}
/**
* 前置通知 - 获取参数名称
* @param joinPoint
*/
@Before(value = "aop()")
public void before(JoinPoint joinPoint){
List<Object> objects = Arrays.asList(joinPoint.getArgs());
System.out.println("前置通知--参数:"+objects);
}
/**
* 后置通知 - 异常依旧可以执行,获取不到返回值
* @param joinPoint
*/
@After("aop()")
public void after(JoinPoint joinPoint){
String method = joinPoint.getSignature().getName();
System.out.println("后置通知--方法名称:"+method);
}
/**
* 后置增强通知 - 异常不执行,可以获取返回值
* @param joinPoint
* @param ret
*/
@AfterReturning(value = "aop()",returning = "ret")
public void afterReturning(JoinPoint joinPoint,Object ret){
String method_name = joinPoint.getSignature().getName();
System.out.println("后置增强通知--方法名称:"+method_name+"--返回值:"+ret);
}
/**
* 后置异常通知 - 当抛出异常后可以获取异常信息
* @param joinPoint
* @param ex
*/
@AfterThrowing(value = "aop()",throwing = "ex")
public void afterException(JoinPoint joinPoint,Exception ex){
String method_name = joinPoint.getSignature().getName();
System.out.println("后置异常通知--方法名称:"+method_name+"--异常:"+ex);
}
}
@Before - 为前置通知: 可以获取到方法的参数 通过JoinPoint.getArgs()方法来获取,参数数组
@After - 为后置通知:后置通知有个特点是不管抛不抛出异常都执行。但是获取不到返回值这个通知
@AfterReturning - 后置增强通知:可以获取到方法的返回值,若改方法抛出异常时,该通知不执行。
@AfterThrowing - 后置异常通知:当方法抛出异常后才执行的通知,可以获取异常信息.
测试======
请求一次http://localhost:8080/index?name=bob&age=18,注意观察循序,因为没有抛出异常所有没有异常通知。
第二次请求,因为抛出异常,所以出现异常通知,但是后置增强通知也回不触发。
接下来是第五种通知
@Around - 环绕通知 简单来说就是4种通知的结合体,
/**
* 环绕通知
* @param joinPoint
* @return
*/
@Around("aop()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知开始");
Object[] args = joinPoint.getArgs();//参数
String method_name = joinPoint.getSignature().getName();//方法名
Object proceed = null;
try {
System.out.println("前置通知--参数:"+ Arrays.asList(args));
proceed = joinPoint.proceed(args);//执行该方法
System.out.println("后置通知--方法名称:"+method_name);
} catch (Throwable throwable) {
System.out.println("后置异常通知--异常:"+throwable.getMessage());
throw throwable;
}
System.out.println("后置增强通知--方法名称:"+method_name+"--返回值:"+proceed);
System.out.println("环绕通知结束");
return proceed;
}
测试 第一次请求,
第二次请求