上接:spring aop创建工程基于注解开发(@Before、@After、@AfterReturning、 @AfterThrowing)
概述
本文介绍 Around 通知
修改 Logger 类
增加下面方法:
@Around("pt()")
public void aroundPrint(){
System.out.println("======around");
}
完整代码
@Component
@Aspect
public class Logger {
@Pointcut("execution(* top.malaoshi.service.*.*(..))")
public void pt(){
}
@Before("pt()")
public void beforePrint(){
System.out.println("=======before");
}
@After("pt()")
public void afterPrint(){
System.out.println("======after");
}
@AfterReturning("pt()")
public void afterReturningPrint(){
System.out.println("======afterReturning");
}
@AfterThrowing("pt()")
public void afterThrowingPrint(){
System.out.println("======异常通知afterThrowingPrint");
}
@Around("pt()")
public void aroundPrint(){
System.out.println("======around");
}
}
修改 UserSrvImpl 类
让该类所有的方法都能 执行成功
完整代码
@Service
public class UserSrvImpl implements IUserService {
public UserSrvImpl(){
System.out.println("UserSrvImpl构造方法");
}
public void save(String username,String password){
// System.out.println("UserSrvImpl保存 报错");
// throw new RuntimeException("UserSrvImpl保存 报错");
System.out.println("UserSrvImpl保存 "+username+"-"+password);
}
public int update(){
System.out.println("UserSrvImpl修改 ");
return 1;
}
public int delete(String id){
System.out.println("UserSrvImpl删除 "+id);
return 2;
}
}
测试-有问题
主启动类
public class Main {
public static void main(String[] args) {
ApplicationContext ac=new AnnotationConfigApplicationContext(ApplicationConfig.class);
IUserService srv=(IUserService)ac.getBean("userSrvImpl");
srv.save("李雷","123456");
// srv.update();
}
}
执行结果如下:
======around
======after
======afterReturning
发现没有执行目标方法
解决问题
around环绕通知 ProceedingJoinPoint 形参
需要在 环绕方法中传入形参 ProceedingJoinPoint ,该类有以下作用:
- 通过该类获取 传入目标方法的形参
- 通过该类 调用目标方法
- 通过该类 获取目标方法的返回结果
修改Logger类的 aroundPrint 方法
@Around("pt()")
public Object aroundPrint(ProceedingJoinPoint pjp) throws Throwable {
Signature s=jp.getSignature();
System.out.println("======around开始 "+"调用 " + s.getDeclaringTypeName()+"."+s.getName()
+ " 方法,参数:" + Arrays.toString(jp.getArgs()));
//获取传入的目标方法的参数
Object[] array=pjp.getArgs();
//调用目标方法,并返回结果
Object res=null;
try {
res = pjp.proceed(array);
System.out.println("======around结束");
}catch (Throwable e){
System.out.println("======around捕捉异常");
throw e;
} finally {
System.out.println("方法结束执行");
}
return res;
}
注意: pjp.proceed() 方法会抛出异常,不要 catch 该异常,否则不会触发 @AfterThrowing 通知
测试-执行成功
执行结果如下:
UserSrvImpl构造方法
======around开始
=======before
UserSrvImpl保存 李雷-123456
======around结束
======after
======afterReturning
执行成功顺序
- around 开始
- before
- 目标方法
- around 结束
- after
- afterReturning
测试-执行抛出异常
修改 UserSrvImpl 的 save()方法
让其抛出异常
public void save(String username,String password){
System.out.println("UserSrvImpl保存 报错");
int i=1/0;
// System.out.println("UserSrvImpl保存 "+username+"-"+password);
}
执行
执行结果如下:
======around开始
=======before
UserSrvImpl保存 报错
======around捕捉异常
======after
======异常通知afterThrowingPrint
执行抛出异常的顺序
- around 开始
- before
- 目标方法
- around 捕捉异常
- after
- afterThrowing
总结
一般使用 @Around 注解可以代替 @Before、@After、@AfterReturning、@AfterThrowing