接着上文:https://blog.csdn.net/single_wolf_wolf/article/details/81772837
多切面 相对来说,只是定义多个切面类,同时配置类中设置一下,
demo如下:
首先定义一个接口:
package com.cmb.multi;
public interface MultiAsp {
public void test();
}
再给出实现:
package com.cmb.multi;
import org.springframework.stereotype.Component;
@Component
public class MultiAspImpl implements MultiAsp {
public void test() {
System.out.println("This is a test for multi aspect!");
}
}
不要忘记@Component
其中test()是连接点
切面一:
package com.cmb.multi;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class Aspect1 {
@Pointcut("execution(* com.cmb.multi.MultiAspImpl.test(..))")
public void print(){
}
@Before("print()")
public void before(){
System.out.println("before 1 ....");
}
@After("print()")
public void after(){
System.out.println("after 1 ....");
}
@AfterReturning("print()")
public void afterReturning(){
System.out.println("afterReturning 1 ....");
}
@AfterThrowing("print()")
public void afterThrowing(){
System.out.println("afterThrowing 1 ....");
}
}
切面二:
package com.cmb.multi;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class Aspect2 {
@Pointcut("execution(* com.cmb.multi.MultiAspImpl.test(..))")
public void print(){
}
@Before("print()")
public void before(){
System.out.println("before 2 ....");
}
@After("print()")
public void after(){
System.out.println("after 2 ....");
}
@AfterReturning("print()")
public void afterReturning(){
System.out.println("afterReturning 2 ....");
}
@AfterThrowing("print()")
public void afterThrowing(){
System.out.println("afterThrowing 2 ....");
}
}
切面三:
package com.cmb.multi;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class Aspect3 {
@Pointcut("execution(* com.cmb.multi.MultiAspImpl.test(..))")
public void print(){
}
@Before("print()")
public void before(){
System.out.println("before 3 ....");
}
@After("print()")
public void after(){
System.out.println("after 3 ....");
}
@AfterReturning("print()")
public void afterReturning(){
System.out.println("afterReturning 3 ....");
}
@AfterThrowing("print()")
public void afterThrowing(){
System.out.println("afterThrowing 3 ....");
}
}
然后给出配置类:MultiConfig
package com.cmb.multi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.cmb.multi")
public class MultiConfig {
@Bean
public Aspect1 getAspect1(){
return new Aspect1();
}
@Bean
public Aspect2 getAspect2(){
return new Aspect2();
}
@Bean
public Aspect3 getAspect3(){
return new Aspect3();
}
}
最后我们测试一下:主函数:
package com.cmb.multi;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MultiMain {
public static void main(String[] args) {
//使用AnnotationConfigApplicationContext 加载配置文件
ApplicationContext ctx = new AnnotationConfigApplicationContext(MultiConfig.class);
MultiAsp multiAsp = ctx.getBean(MultiAsp.class);
multiAsp.test();
}
}
结果如下:
before 1 ....
before 2 ....
before 3 ....
This is a test for multi aspect!
after 3 ....
afterReturning 3 ....
after 2 ....
afterReturning 2 ....
after 1 ....
afterReturning 1 ....
结果很尴尬,和书本上不一致,书上说目前这种写法的话,多个切面是无序的,结果应该是
before 1 ....
before 3 ....
before 2 ....
This is a test for multi aspect!
after 2 ....
afterReturning 2 ....
after 3 ....
afterReturning 3 ....
after 1 ....
afterReturning 1 ....
但是,笔者不信邪,连续运行了十几次,结果还是第一种,目前猜测是我的框架比较新,不知道是不是框架内部默认了顺序,探后我修改MultiConfig配置类如下:
@Bean
public Aspect3 getAspect3(){
return new Aspect3();
}
@Bean
public Aspect1 getAspect1(){
return new Aspect1();
}
@Bean
public Aspect2 getAspect2(){
return new Aspect2();
}
对,就是把Aspect3放到了最上面的位置,然后查看结果如下:
before 3 ....
before 1 ....
before 2 ....
This is a test for multi aspect!
after 2 ....
afterReturning 2 ....
after 1 ....
afterReturning 1 ....
after 3 ....
afterReturning 3 ....
结果居然变换了,目前看来,Spring AOP框架中关于多个切面的执行顺序是按照配置类中Bean的注入来的。
然后我们使用@Order 把切面分别修改为:
@Aspect
@Order(3)
@Aspect
@Order(1)
@Aspect
@Order(2)
同时配置类中Bean顺序还是3, 1 ,2
运行主函数,结果如下:
before 1 ....
before 2 ....
before 3 ....
This is a test for multi aspect!
after 3 ....
afterReturning 3 ....
after 2 ....
afterReturning 2 ....
after 1 ....
afterReturning 1 ....
看到没!!! 运行顺序被掰过来, 对吧,这个就是@Order的功劳,这里就是使用这个注解规定多切面的执行顺序,最后给出一张图,SPringAOP的多代理情况下,,使用的是责任链模式:
参考文献:《javaEE互联网轻量级框架整合开发》