前言
记录学习历程,上一节
上一节基于xml配置文件实现了前置通知
基于XML配置文件的AOP实现
返回通知
返回通知在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容
例:
(1)在上一节中的日志通知类LogAdvice中添加方法:
//此方法将为返回通知
public void MyAfterReturnAdvice(JoinPoint afterjoinPoint){
List<Object> list= Arrays.asList(afterjoinPoint.getArgs());
//日志格式字符串
String logInfo="返回通知:"+
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+
" "+list.get(0).toString()+" 浏览商品: "+list.get(1).toString();
System.out.println(logInfo);
}
(2)修改xml配置文件
在< aop:aspect >元素中添加< aop:after-returning >
< aop:after-returning>与< aop:after>的区别:
after的执行是在after returning之后,但无论方法是否正常结束, after通知都会被执行
这是后面异常通知测试的< aop:after-returning>与< aop:after>的区别
<aop:after-returning method="MyAfterReturnAdvice" pointcut-ref="logpointcut"/>
可以看出在业务方法browse执行后才输出日志通知类中的返回通知方法产生的日志记录
异常通知
异常通知在连接点抛出异常后执行
例:
(1)在日志通知类LogAdvice中添加方法
//此方法为异常通知
public void MyThrowingAdvice(JoinPoint throwingPoint){
//获取被调用的类名
String targetClassName=throwingPoint.getTarget().getClass().getName();
//获取被调用的方法名
String targetMethodName=throwingPoint.getSignature().getName();
//日志格式字符串
String logInfo="异常通知:执行"+targetClassName+"类的"+
targetMethodName+"方法时发生异常";
System.out.println(logInfo);
}
(2)修改MealServiceImpl类,人为抛出一个异常
package com.BeforeAdvice.Impl;
import com.BeforeAdvice.Service.MealService;
import org.springframework.stereotype.Service;
@Service("mealService")
public class MealServiceImpl implements MealService {
@Override
public void browse(String LoginName, String mealName) {
System.out.println("执行业务方法browse");
//人为抛出异常
throw new RuntimeException("这是一个人为抛出的异常");
}
}
(3)xml配置
<aop:after-throwing method="MyThrowingAdvice" pointcut-ref="logpointcut" />
环绕通知
环绕通知围绕在连接点前后,比如一个方法调用的前后,这是最强大的通知类型,能在方法调用前后自定义一些操作,环绕通知还需要负责决定是继续处理joinpoint(调用ProeedingJoinPoint的proceed方法)还是中断执行
例:
(1)在日志通知类LogAdvice中添加方法
//此方法为环绕通知
public void MyAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
long beginTime=System.currentTimeMillis();
proceedingJoinPoint.proceed();
long endTime=System.currentTimeMillis();
//获得被调用的方法名
String targetMethodName=proceedingJoinPoint.getSignature().getName();
//日志格式字符串
String logInfo="环绕通知:"+targetMethodName+"方法调用前时间"+
beginTime+"毫秒,"+"调用后时间"+endTime+"毫秒";
System.out.println(logInfo);
}
(2)修改MealServiceImpl类中browse方法
通过while循环延长方法的执行时间
int i=10000000;
while (i>0){
i--;
}
(3)修改xml配置文件
将LogAdvice中的MyAroundAdvice方法指定为环绕通知
<aop:around method="MyAroundAdvice" pointcut-ref="logpointcut"/>
(4)测试
可以看出环绕通知可以记录业务方法browse执行前后的时间