Spring AOP(八)AOP多切面编程

AOP多切面编程

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------------");
    }
}

这样我们就定义了三个切面,它们同时拦截UserServiceImplmanyAspects()方法

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就会调用了UserServiceImpl的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注解

我们使用@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接口

同样地,使用Ordered接口也可以指定顺序。

package com.lay.springboot_aop.aspect;

@Aspect
public class MyAspect1 implements Ordered{
    
	//指定顺序
    @Override
    public int getOrder(){
        return 1;
    }
    //.......
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值