1.xml方式
部分通知执行先后顺序取决于配置的顺序
/**
* 切面类
*/
public class MyAspect {
//前置通知
public void before(){
System.out.println("before......");
}
//环绕通知 Proceeding JoinPoint:正在执行的连接点-->切点
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("around-前....");
Object result = joinPoint.proceed();
System.out.println("around-后....");
return result;
}
//后置通知
//res接收目标对象方法返回值
public void afterReturning(Object res){
System.out.println("afterReturning.....");
System.out.println("res:"+res);
}
//异常抛出通知
public void afterThrowing(){
System.out.println("afterThrowing....");
}
//最终通知
public void after(){
System.out.println("after.....");
}
}
<!--配置织入:告诉Spring框架 哪些方法(切点)需要进行哪些增强/通知(前置、后置等等)-->
<aop:config>
<!--声明切面-->
<aop:aspect ref="myAspect">
<!--切面:切点+通知-->
<!--抽取切点-->
<aop:pointcut id="pointcut" expression="execution(* com.itheima.aop.*.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:around method="around" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="res"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
/**
* 目标对象
*/
public class Target implements TargetInterface {
@Override
public int save() {
System.out.println("save running.....");
// int i=1/0;
return 10;
}
}
1.1.可以看到,先配置前置通知before,再配置环绕通知around,正常情况下的执行顺序:
1.2.先配置环绕通知around,再配置前置通知before ,正常情况下的执行顺序:
1.3.异常情况:
@Override
public int save() {
System.out.println("save running.....");
int i=1/0;
return 10;
}
1.4.总结:
1.前置通知before和环绕通知around的执行顺序取决于配置顺序, 后置通知afterReturning和最终通知after执行顺序取决于配置顺序
按上面的配置来看:
2.正常情况:before(或around-前)-->目标方法-->(around-后)-->afterReturning-->after
3.异常情况:before(或around-前)-->目标方法-->afterThrowing-->after
4.无论正常还是异常都会执行的通知:before、around-前、after;正常多一个afterReturning和around-后 ;异常多一个afterThrowing
2.注解方式
/**
* 切面类
*/
@Component
@Aspect
public class MyAspect {
//配置切点
@Pointcut("execution(* com.itheima.anno.*.*(..))")
public void pointcut(){}
//环绕通知 Proceeding JoinPoint:正在执行的连接点-->切点
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("around-前....");
Object result = joinPoint.proceed();
System.out.println("around-后....");
return result;
}
//前置通知
@Before("pointcut()")
public void before(){
System.out.println("before......");
}
//后置通知
//res接收目标对象方法返回值
@AfterReturning(value = "pointcut()",returning = "res")
public void afterReturning(Object res){
System.out.println("afterReturning.....");
System.out.println("res:"+res);
}
//异常抛出通知
@AfterThrowing("pointcut()")
public void afterThrowing(){
System.out.println("afterThrowing....");
}
//最终通知
@After("pointcut()")
public void after(){
System.out.println("after.....");
}
}
/**
* 目标对象
*/
@Component
public class Target implements TargetInterface {
@Override
public int save() {
System.out.println("save running.....");
// int i=1/0;
return 10;
}
}
2.1.注解方式环绕通知around比前置通知before先执行,与编写顺序无关,after通知比afterReturning先执行,正常如下:
2.2.异常情况:
2.3.总结:
1)正常情况:around-前-->before-->目标-->around-后-->after-->afterReturning
2)异常情况:around-前-->before-->目标-->after-->afterThrowing
3)正常或异常都执行的通知:around-前、before、after ;正常多一个afterReturning在最后和around-后;异常多一个afterThrowing在最后
3.两者区别
xml方式通知执行顺序受配置顺序影响,注解方式固定