一、Advice执行顺序
如果多个Advice和同一个JointPoint连接,我们需要指明每一个Advice的执行顺序,那么我们就需要分两种情况讨论,
- 第一种是如果Advice在同一个Aspect当中,那么执行的顺序是按照Advice在Aspect的声明顺序执行的。
- 如果Advice在不同的Aspect当中,那么执行的顺序是需要将Aspect继承Ordered这个类,然后覆写getOrder方法
二、Advice在同一个Aspect中
AdviceOrder.java 在这个Aspect中我们指明了Pointcut和Advice的类型,我们可以看到,两个Before类型的Advice切入到了同一个JointPoint上,两个AfterReturning类型的Advice切入到了同一个JointPoint上。
package com.zbt.day04;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AdviceOrder {
@Pointcut("execution(* com.zbt.day04.*.*(..))")
public void methodPoint(){
}
@Before("methodPoint()")
public void beforeAdviceI(){
System.out.println("before advice I 执行了");
}
@Before("methodPoint()")
public void beforeAdviceII(){
System.out.println("before advice II 执行了");
}
@AfterReturning("methodPoint()")
public void afterReturningI(){
System.out.println("After Returning Advice I 执行了");
}
@AfterReturning("methodPoint()")
public void afterReturningII(){
System.out.println("After Returning Advice I 执行了");
}
}
TargetClass.java 这是一个目标类,其中的sayHello方法是JointPoint
package com.zbt.day04;
public class TargetClass {
public void sayHello(){
System.out.println("Hello,What a good day!");
}
}
XML配置文档
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<bean id="adviceOrder" class="com.zbt.day04.AdviceOrder"></bean>
<bean id="targetClass" class="com.zbt.day04.TargetClass"></bean>
</beans>
TestTargetClass.java 测试类
package com.zbt.day04;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAdvice {
@Test
public void testTargetClass(){
ApplicationContext context = new ClassPathXmlApplicationContext("day04_config.xml");
TargetClass targetClass = context.getBean("targetClass",TargetClass.class);
targetClass.sayHello();
}
}
测试结果
before advice I 执行了
before advice II 执行了
Hello,What a good day!
After Returning Advice I 执行了
After Returning Advice II 执行了
从结果我们可以看到,这个beforeAdviceI在beforeAdviceII之前执行,而afterReturningI在afterReturningII之前执行了,正好印证了我们之前所说的在同一个Aspect内,那么如果多个相同类型的Advice连接到同一个JointPoint上,此时执行的顺序就是按照Advice在Aspect中声明的顺序执行的。
三、Advice在不同的Aspect中
如果有多个Aspect的相同类型的Advice切入同一个JointPoint当中,如果我们想要指定这写Advice执行的顺序,因此我们的Aspect需要继承org.springframework.core.Ordered这个类。
AdviceOrderI.java 这个类是一个Aspect继承了Order方法,同时覆写了getOrder方法。切入com.zbt.day05中所有的方法。提供了一个BeforeAdvice和一个AfterAdvice,同时
package com.zbt.day05;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;
@Aspect
public class AdviceOrderI implements Ordered{
@Pointcut("execution(* com.zbt.day05.*.*(..))")
public void pointI(){
}
@Before("pointI()")
public void beforeAdviceI(){
System.out.println("AdviceOrderI 的 Before Advice I 执行了");
}
@AfterReturning("pointI()")
public void afterReturningI(){
System.out.println("AdviceOrderI 的 After Returning Advice I 执行了");
}
@Override
public int getOrder() {
return 20;
}
}
AdviceOrderII.java同样也继承了Ordered类,最后
package com.zbt.day05;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;
@Aspect
public class AdviceOrderII implements Ordered{
@Pointcut("com.zbt.day05.AdviceOrderI.pointI()")//复用Advice
public void pointII(){}
@Before("pointII()")
public void beforeAdviceII(){
System.out.println("AdviceOrderII 的 Before Advice II 执行了");
}
@AfterReturning("pointII()")
public void afterReturningII(){
System.out.println("AdviceOrderII 的 After Returning Advice II 执行了");
}
@Override
public int getOrder() {
return 10;
}
}
TargetClass.java是一个目标类,sayHello是一个JointPoint
package com.zbt.day05;
public class TargetClass {
public void sayHello(){
System.out.println("Hello,What a good day!");
}
}
XML配置文档
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<bean id="adviceOrderI" class="com.zbt.day05.AdviceOrderI"></bean>
<bean id="adviceOrderII" class="com.zbt.day05.AdviceOrderII"></bean>
<bean id="targetClass" class="com.zbt.day05.TargetClass"></bean>
</beans>
TestTargetClass测试类
package com.zbt.day05;
import com.zbt.day04.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestTargetClass {
@Test
public void testTargetClass(){
ApplicationContext context = new ClassPathXmlApplicationContext("day05_config.xml");
TargetClass targetClass = context.getBean("targetClass", TargetClass.class);
targetClass.sayHello();
}
}
输出结果
AdviceOrderII 的 Before Advice II 执行了
AdviceOrderI 的 Before Advice I 执行了
Hello,What a good day!
AdviceOrderI 的 After Returning Advice I 执行了
AdviceOrderII 的 After Returning Advice II 执行了
从结果我们也可以看如果我们的Ordered返回的order越小,那么这个Aspect的BeforeAdvice就会在前面执行,而AfterReturning类型的Advice就会在后面执行。