Spring可以支持多个切面的运行。
首先我们来创建3个切面类。
MyAspect1
package com.lay.springboot_aop.aspect;
@Aspect
public class MyAspect1 {
@Pointcut("execution(* com.lay.springboot_aop.aspect.service.impl.UserServiceImpl.printUser(..))")
public void pointCut() {
}
@Before("pointCut()")
public void before(JoinPoint point ,User user) {
System.out.println("MyAspect1 before-----------");
}
@After("pointCut()")
public void after() {
System.out.println("MyAspect1 after------------");
}
@AfterReturning("pointCut()")
public void afterReturning() {
System.out.println("MyAspect1 afterReturning------------");
}
@AfterThrowing("pointCut()")
public void afterThrowning() {
System.out.println("MyAspect1 afterThrowning------------");
}
}
MyAspect2
package com.lay.springboot_aop.aspect;
@Aspect
public class MyAspect2 {
@Pointcut("execution(* com.lay.springboot_aop.aspect.service.impl.UserServiceImpl.printUser(..))")
public void pointCut() {
}
@Before("pointCut()")
public void before(JoinPoint point ,User user) {
System.out.println("MyAspect2 before-----------");
}
@After("pointCut()")
public void after() {
System.out.println("MyAspect2 after------------");
}
@AfterReturning("pointCut()")
public void afterReturning() {
System.out.println("MyAspect2 afterReturning------------");
}
@AfterThrowing("pointCut()")
public void afterThrowning() {
System.out.println("MyAspect2 afterThrowning------------");
}
}
MyAspect3
package com.lay.springboot_aop.aspect;
@Aspect
public class MyAspect3 {
@Pointcut("execution(* com.lay.springboot_aop.aspect.service.impl.UserServiceImpl.printUser(..))")
public void pointCut() {
}
@Before("pointCut()")
public void before(JoinPoint point ,User user) {
System.out.println("MyAspect3 before-----------");
}
@After("pointCut()")
public void after() {
System.out.println("MyAspect3 after------------");
}
@AfterReturning("pointCut()")
public void afterReturning() {
System.out.println("MyAspect3 afterReturning------------");
}
@AfterThrowing("pointCut()")
public void afterThrowning() {
System.out.println("MyAspect3 afterThrowning------------");
}
}
这样我们就定义了三个切面,它们同时拦截UserServiceImpl
的manyAspects()
方法
UserServiceImpl
public class UserServiceImpl implements UserService{
@override
public void manyAspects(){
system.out.println("测试多个切面顺序");
}
}
接着在UserController
控制器中加入新的方法,已方便我们测试。
UserController
@Controller @RequestMapping("/user") public class UserController{
// 注入用户服务service @Autowired private UserService userService; @RequestMapping("/manyAspects") public String manyAspects(){ userService.manyAspects(); return "manyAspects"; }
}
这样我们通过浏览器地址栏输入URL就会调用了UserServiceImp
l的manyAspects
方法,然后再配置文件中加入3个切面的Bean。
SpringbootAopApplication
启动主函数
package com.lay.springboot_aop;
//@SpringBootApplication(scanBasePackages= {“com.lay.springboot_aop.aspect”})
@SpringBootApplication
public class SpringbootAopApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootAopApplication.class, args);
}
// 切面1
@Bean(name="myAspect1")
public MyAspect initMyAspect() {
return new MyAspect1();
}
// 切面2
@Bean(name="myAspect2")
public MyAspect initMyAspect() {
return new MyAspect2();
}
// 切面3
@Bean(name="myAspect3")
public MyAspect initMyAspect() {
return new MyAspect3();
}
}
运行测试,日志如下
myAspect2 before-------
myAspect1 before-------
myAspect3 before-------
测试多个切面
myAspect3 after--------
myAspect3 afterReturning--------
myAspect1 after--------
myAspect1 afterReturning--------
myAspect2 after--------
myAspect2 afterReturning--------
从日志中可以看出,切面的执行顺序是乱的。
我们需要确定切面的执行顺序,来决定哪些切面先执行,哪些切面后执行。为此,Spring提供了注解@Order来一个接口Ordered
,它们都可以来指定切面的顺序。
我们使用@Order注解制定MyAspect1
顺序为1
package com.lay.springboot_aop.aspect;
@Aspect
@Order(1)
public class MyAspect1 {
//…
}
同样的,我们也可以指定MyAspect2
的顺序为2,MyAspect3
的顺序为3,再次进行测试
打印日志
myAspect1 before-------
myAspect2 before-------
myAspect3 before-------
测试多个切面
myAspect3 after--------
myAspect3 afterReturning--------
myAspect2 after--------
myAspect2 afterReturning--------
myAspect1 after--------
myAspect1 afterReturning--------
我们可以看到对于前置通知(before)都是从小到大运行的,而对于后置通知和返回通知都是从大到小运行的,这就是典型的责任链模式的顺序。
同样地,使用Ordered
接口也可以指定顺序。
package com.lay.springboot_aop.aspect;
@Aspect
public class MyAspect1 implements Ordered{
//指定顺序
@Override
public int getOrder(){
return 1;
}
//.......
}