SpringAOP的四种通知类型:前置通知、异常通知、后置通知、异常通知
一、四种常见的通知类型
给出 账户的业务层接口 IAccountService.java,
为了便于演示这四种通知类型,我们就只留下了一个方法。
public interface IAccountService {
void saveAccount();
}
给出 账户的业务层接口的实现类 AccountServiceImpl.java
public class AccountServiceImpl implements IAccountService{
@Override
public void saveAccount() {
System.out.println("执行了保存");
//int i=1/0;
}
}
给出一个日志类, 用于打印日志
public class Logger {
/**
* 前置通知
*/
public void beforePrintLog(){
System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志了。。。");
}
/**
* 后置通知
*/
public void afterReturningPrintLog(){
System.out.println("后置通知Logger类中的afterReturningPrintLog方法开始记录日志了。。。");
}
/**
* 异常通知
*/
public void afterThrowingPrintLog(){
System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。");
}
/**
* 最终通知
*/
public void afterPrintLog(){
System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。");
}
}
给出配置信息bean.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
注意:
1)异常通知和后置通知永远只能执行一个
2)配置切入点表达式
此标签写在aop:aspect标签内部只能当前切面使用。
它还可以写在aop:aspect外面,此时就变成了所有切面可用
给出Test类
public class AOPTest {
public static void main(String[] args) {
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.获取对象
IAccountService as = (IAccountService)ac.getBean("accountService");
//3.执行方法
as.saveAccount();
}
}
执行结果:
当我们放开AccountServiceImpl类中我们故意制造的异常 int i=1/0;时:
二、环绕通知
环绕通知,只需要稍稍微改变上面例子的两点即可
(1)改动日志类 Logger.java
public class Logger {
public Object aroundPringLog(ProceedingJoinPoint pjp){
Object rtValue = null;
try{
Object[] args = pjp.getArgs();//得到方法执行所需的参数
System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置");
rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)
System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置");
return rtValue;
}catch (Throwable t){
System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常");
throw new RuntimeException(t);
}finally {
System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终");
}
}
}
注意:pjp.proceed(args)会报异常,必须用 Throwable t,因为Exception拦不住它
(2)改动配置文件
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
分析:
spring中的环绕通知是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。
Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点方法。该接口可以作为环绕通知的方法参数,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。