接着上文: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 {@Beanpublic Aspect1 getAspect1(){return new Aspect1();}@Beanpublic Aspect2 getAspect2(){return new Aspect2();}@Beanpublic 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配置类如下:
@Beanpublic Aspect3 getAspect3(){return new Aspect3();}@Beanpublic Aspect1 getAspect1(){return new Aspect1();}@Beanpublic 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互联网轻量级框架整合开发》